From 578198e2e6cc9449546dd7d8b4227cc10eed5e59 Mon Sep 17 00:00:00 2001 From: Paul Huynh Date: Mon, 22 Jan 2018 23:25:54 +1100 Subject: [PATCH 01/28] Add Typescript Definitions for Cloud Firestore --- lib/index.d.ts | 280 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) diff --git a/lib/index.d.ts b/lib/index.d.ts index 8d300c6f..38c0308d 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -72,6 +72,15 @@ declare module "react-native-firebase" { */ links(): RNFirebase.links.Links; + /** + * Cloud Firestore is Firebase's new flagship database solution for mobile + * development, however as at the time of this writing (22 Jan 2018) it is + * still a beta product, and may not be as stable as Firebase Realtime + * Database. Comparison of the two products hers: + * https://firebase.google.com/docs/database/rtdb-vs-firestore + */ + firestore(): RNFirebase.firestore.FirestoreModule; + static fabric: { crashlytics(): RNFirebase.crashlytics.Crashlytics; }; @@ -1067,5 +1076,276 @@ declare module "react-native-firebase" { }, } } + + namespace firestore { + type FirestoreModule = Firestore & FirestoreStatics; + + interface Firestore { + batch(): WriteBatch; + collection(collectionPath: string): CollectionReference; + doc(documentPath: string): DocumentReference; + + /** NOT SUPPORTED YET */ + enablePersistence(): Promise; + /** NOT SUPPORTED YET */ + runTransaction(): Promise; + /** NOT SUPPORTED YET */ + settings(): void; + } + + interface FirestoreStatics { + FieldPath: typeof FieldPath; + FieldValue: typeof FieldValue; + GeoPoint: typeof GeoPoint; + enableLogging(enabled: boolean): void; + }; + + class CollectionReference { + constructor(firestore: Firestore, collectionPath: Path); + get firestore(): Firestore; + get id(): string; + get parent(): DocumentReference; + add(data: object): Promise; + doc(documentPath?: string): DocumentReference; + endAt(snapshot: DocumentSnapshot): Query; + endAt(...varargs: any[]): Query; + endBefore(snapshot: DocumentSnapshot): Query; + endBefore(...varargs: any[]): Query; + get(): Promise; + limit(limit: number): Query; + onSnapshot(onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void; + onSnapshot(observer: 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; + } + + class DocumentChange { + constructor(firestore: Firestore, nativeData: Types.NativeDocumentChange); + get doc(): DocumentSnapshot; + get newIndex(): number; + get oldIndex(): number; + get type(): string; + } + + class DocumentReference { + constructor(firestore: Firestore, documentPath: Path); + get firestore(): Firestore; + get id(): string | null; + get parent(): CollectionReference; + get path(): string; + collection(collectionPath: string): CollectionReference; + delete(): Promise; + get(): Promise; + 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; + update(obj: object): Promise; + update(key1: Types.UpdateKey, val1: any): Promise; + update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any): Promise; + update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any): Promise; + update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any, key4: Types.UpdateKey, val4: any): Promise; + 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; + } + namespace DocumentReference { + // JS code expects this value to be true. + interface DocumentListenOptions { + includeMetadataChanges: true; + } + + type ObserverOnNext = (documentSnapshot: DocumentSnapshot) => void; + type ObserverOnError = (err: object) => void; + interface Observer { + next: ObserverOnNext; + error?: ObserverOnError; + } + } + + class DocumentSnapshot { + constructor(firestore: Firestore, nativeData: Types.NativeDocumentSnapshot) + get exists(): boolean; + get id(): string | null; + get metadata(): Types.SnapshotMetadata; + get 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); + get latitude(): number; + get longitude(): number; + } + + class Path { + static fromName(name: string): Path; + constructor(pathComponents: string[]); + get id(): string | null; + get isDocument(): boolean; + get isCollection(): boolean; + get relativeName(): string; + child(relativePath: string): Path; + parent(): Path | null; + } + + class Query { + constructor( + firestore: Firestore, + path: Path, + fieldFilters?: Query.FieldFilter[], + fieldOrders?: Query.FieldOrder[], + queryOptions?: Query.QueryOptions, + ); + get firestore(): Firestore; + endAt(snapshot: DocumentSnapshot): Query; + endAt(...varargs: any[]): Query; + endBefore(snapshot: DocumentSnapshot): Query; + endBefore(...varargs: any[]): Query; + get(): Promise; + limit(limit: number): Query; + onSnapshot(onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void; + onSnapshot(observer: 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 true. This logic is + // encapsulated in QueryListenOptions. + interface _IncludeDocumentMetadataChanges { + includeDocumentMetadataChanges: true; + } + interface _IncludeQueryMetadataChanges { + includeQueryMetadataChanges: true + } + type QueryListenOptions = _IncludeDocumentMetadataChanges | _IncludeQueryMetadataChanges | (_IncludeDocumentMetadataChanges & _IncludeQueryMetadataChanges); + + type ObserverOnNext = (querySnapshot: QuerySnapshot) => void; + type ObserverOnError = (err: object) => void; + interface Observer { + next: ObserverOnNext; + error?: ObserverOnError; + } + } + + class QuerySnapshot { + constructor(firestore: Firestore, query: Query, nativeData: QuerySnapshot.NativeData); + get docChanges(): DocumentChange[]; + get docs(): DocumentSnapshot[]; + get empty(): boolean; + get metadata(): Types.SnapshotMetadata; + get query(): Query; + get size(): number; + forEach(callback: (snapshot: DocumentSnapshot) => any); + } + namespace QuerySnapshot { + interface NativeData { + changes: Types.NativeDocumentChange[]; + documents: Types.NativeDocumentSnapshot[]; + metadata: Types.SnapshotMetadata; + } + } + + class WriteBatch { + constructor(firestore: Firestore); + commit(): Promise; + 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; + } + } + } } } From 17701810588b0cab4380de7382e0d9b632188738 Mon Sep 17 00:00:00 2001 From: Daniel Waller Date: Fri, 26 Jan 2018 13:34:06 +0100 Subject: [PATCH 02/28] [typings][typescript]: fix stupid typo I introduced with my last PR that breaks tsc compilation --- lib/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index 8d300c6f..117ca16e 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -643,7 +643,7 @@ declare module "react-native-firebase" { } /** 3rd party provider Credentials */ - type AuthCredential { + type AuthCredential = { providerId: string, token: string, secret: string @@ -1034,7 +1034,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: From 2f21a37f7d0bf09ef555d92f66b18c070f891aea Mon Sep 17 00:00:00 2001 From: Daniel Waller Date: Fri, 26 Jan 2018 17:38:13 +0100 Subject: [PATCH 03/28] [typings][typescript] add validation of ts declaration file to build process --- package.json | 6 ++++-- tsconfig.json | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tsconfig.json diff --git a/package.json b/package.json index 55cf3c33..ece638dd 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "scripts": { "build": "genversion lib/version.js && npm run build-lib && npm run build-flow", "build-flow": "flow-copy-source -i */__tests__* lib dist", - "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", + "build-lib": "npm run validate-ts-declarations && BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", "clean": "rimraf dist/", "flow": "flow", "format": "eslint --fix ./lib ./tests/src ./tests/lib", @@ -21,7 +21,8 @@ "tests-npm-install": "cd tests && npm install", "tests-pod-install": "cd tests && npm run ios:pod:install", "tests-watch-start": "npm run test-cli watch init start", - "tests-watch-stop": "npm run test-cli watch stop" + "tests-watch-stop": "npm run test-cli watch stop", + "validate-ts-declarations": "tsc --project ./" }, "repository": { "type": "git", @@ -101,6 +102,7 @@ "react-native": "^0.52.0", "rimraf": "^2.6.2", "shelljs": "^0.7.8", + "typescript": "^2.6.2", "wml": "0.0.82" }, "dependencies": { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..550ece32 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "jsx": "react", + "sourceMap": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "lib": [ + "es2015", + "es2016", + "esnext", + "dom" + ] + }, + "files": [ + "./lib/index.d.ts" + ] +} From 42fe8ddd656f85c4cae7442ff5b47b68b957cf50 Mon Sep 17 00:00:00 2001 From: Daniel Waller Date: Fri, 26 Jan 2018 17:39:52 +0100 Subject: [PATCH 04/28] [typings][typescript] fix tsc errors --- lib/index.d.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index 117ca16e..36750b9f 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -5,6 +5,13 @@ declare module "react-native-firebase" { + /** 3rd party provider Credentials */ + type AuthCredential = { + providerId: string, + token: string, + secret: string + } + type AuthProvider = { PROVIDER_ID: string, credential: (token: string, secret?: string) => AuthCredential, @@ -594,7 +601,7 @@ declare module "react-native-firebase" { * * @param forceRefresh: boolean - default to false */ - getIdToken(forceRefresh: boolean?): Promise + getIdToken(forceRefresh?: boolean): Promise /** * Link the user with a 3rd party credential provider. @@ -642,13 +649,6 @@ declare module "react-native-firebase" { updateProfile(updates: UpdateProfile): Promise } - /** 3rd party provider Credentials */ - type AuthCredential = { - providerId: string, - token: string, - secret: string - } - type ActionCodeSettings = { android: { installApp?: boolean, @@ -1032,7 +1032,7 @@ declare module "react-native-firebase" { * Returns an unsubscribe function, call the returned function to * unsubscribe from all future events. */ - onLink(listener: (url) => void): () => void; + onLink(listener: (url: string) => void): () => void; } /** From 2bd4a667a99412f7e83810fce91eb3b6afa5f05b Mon Sep 17 00:00:00 2001 From: Paul Huynh Date: Mon, 29 Jan 2018 16:14:06 +1100 Subject: [PATCH 05/28] Fix TS definitions so modules can be accessed from the default export --- lib/index.d.ts | 161 ++++++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 76 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index 8d300c6f..b18ebd4c 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -5,88 +5,68 @@ declare module "react-native-firebase" { - type AuthProvider = { - PROVIDER_ID: string, - credential: (token: string, secret?: string) => AuthCredential, + type FirebaseModuleAndStatics = { + (): M; + nativeModuleExists: boolean; + } & S + + // Modules commented-out do not currently have type definitions + export class Firebase { + private constructor(); + // admob: FirebaseModuleAndStatics; + analytics: FirebaseModuleAndStatics; + auth: FirebaseModuleAndStatics; + // config: FirebaseModule; + crash: FirebaseModuleAndStatics; + database: FirebaseModuleAndStatics; + fabric: { + crashlytics: FirebaseModuleAndStatics; }; + // firestore: FirebaseModuleAndStatics; + links: FirebaseModuleAndStatics; + messaging: FirebaseModuleAndStatics; + // perf: FirebaseModuleAndStatics; + storage: FirebaseModuleAndStatics; + // utils: FirebaseModuleAndStatics; + initializeApp(options: Firebase.Options, name: string): App; + app(name?: string): App; + apps(): App[]; + SDK_VERSION(): string; + } + namespace Firebase { + interface Options { + apiKey: string; + appId: string; + databaseURL: string; + messagingSenderId: string; + projectId: string; + storageBucket: string; + } + } + const firebase: Firebase; + export default firebase; - export default class FireBase { - constructor(config?: RNFirebase.configurationOptions) - - log: any; - + // Modules commented-out do not currently have type definitions + export class App { + private constructor(); + // admob(): RNFirebase.admob.AdMob; analytics(): RNFirebase.Analytics; - - on(type: string, handler: (msg: any) => void): any; - - database: { - (): RNFirebase.database.Database - ServerValue: { - TIMESTAMP: number - } - }; - - auth: { - (): RNFirebase.auth.Auth - EmailAuthProvider: AuthProvider, - PhoneAuthProvider: AuthProvider, - GoogleAuthProvider: AuthProvider, - GithubAuthProvider: AuthProvider, - TwitterAuthProvider: AuthProvider, - FacebookAuthProvider: AuthProvider, - PhoneAuthState: { - CODE_SENT: string, - AUTO_VERIFY_TIMEOUT: string, - AUTO_VERIFIED: string, - ERROR: string, - }, - }; - - /**RNFirebase mimics the Web Firebase SDK Storage, - * whilst providing some iOS and Android specific functionality. - */ - storage(): RNFirebase.storage.Storage; - - /** - * Firebase Cloud Messaging (FCM) allows you to send push messages at no cost to both Android & iOS platforms. - * Assuming the installation instructions have been followed, FCM is ready to go. - * As the Firebase Web SDK has limited messaging functionality, - * the following methods within react-native-firebase have been created to handle FCM in the React Native environment. - */ - messaging(): RNFirebase.messaging.Messaging; - - /** - * RNFirebase provides crash reporting for your app out of the box. - * Please note crashes do not appear in real-time on the console, - * they tend to take a number of hours to appear - * If you want to manually report a crash, - * such as a pre-caught exception this is possible by using the report method. - */ + auth(): RNFirebase.auth.Auth; + // config(): RNFirebase.config.Config; crash(): RNFirebase.crash.Crash; - - /** - * Firebase Dynamic Links are links that work the way you want, on multiple - * platforms, and whether or not your app is already installed. - * See the official Firebase docs: - * https://firebase.google.com/docs/dynamic-links/ - */ - links(): RNFirebase.links.Links; - - static fabric: { - crashlytics(): RNFirebase.crashlytics.Crashlytics; + database(): RNFirebase.database.Database; + fabric: { + crashlytics(): RNFirebase.crashlytics.Crashlytics, }; - - apps: Array; - googleApiAvailability: RNFirebase.GoogleApiAvailabilityType; - - static initializeApp(options?: any | RNFirebase.configurationOptions, name?: string): FireBase; - - static app(name?: string): FireBase; - - [key: string]: any; + // firestore(): RNFirebase.firestore.Firestore; + links(): RNFirebase.links.Links; + messaging(): RNFirebase.messaging.Messaging; + // perf(): RNFirebase.perf.Performance; + storage(): RNFirebase.storage.Storage; + // utils(): RNFirebase.utils.Utils; } - namespace RNFirebase { + export namespace RNFirebase { interface RnError extends Error { code?: string; } @@ -484,6 +464,15 @@ declare module "react-native-firebase" { update(values: Object, onComplete?: (a: RnError | null) => any): Promise; } + + interface DatabaseStatics { + /** @see https://www.firebase.com/docs/java-api/javadoc/com/firebase/client/ServerValue.html#TIMESTAMP */ + ServerValue: { + TIMESTAMP: { + [key: string]: string + } + } + } } /** @@ -643,7 +632,7 @@ declare module "react-native-firebase" { } /** 3rd party provider Credentials */ - type AuthCredential { + type AuthCredential = { providerId: string, token: string, secret: string @@ -711,6 +700,11 @@ declare module "react-native-firebase" { user: object | null } | null; + type AuthProvider = { + PROVIDER_ID: string, + credential: (token: string, secret?: string) => AuthCredential, + }; + interface Auth { /** * Returns the current Firebase authentication state. @@ -828,6 +822,21 @@ declare module "react-native-firebase" { [key: string]: any; } + + interface AuthStatics { + EmailAuthProvider: AuthProvider; + PhoneAuthProvider: AuthProvider; + GoogleAuthProvider: AuthProvider; + GithubAuthProvider: AuthProvider; + TwitterAuthProvider: AuthProvider; + FacebookAuthProvider: AuthProvider; + PhoneAuthState: { + CODE_SENT: string; + AUTO_VERIFY_TIMEOUT: string; + AUTO_VERIFIED: string; + ERROR: string; + }; + } } namespace messaging { From 80be7474ff231590508e9dbbfa3d58b817990df0 Mon Sep 17 00:00:00 2001 From: Paul Huynh Date: Mon, 29 Jan 2018 20:55:18 +1100 Subject: [PATCH 06/28] Address typing issues: - Remove constructors intended to be private, and convert classes to interfaces - Allow 'false' for QueryListenOptions and DocumentListenOptions properites --- lib/index.d.ts | 95 +++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index 38c0308d..0861f2ca 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -79,7 +79,9 @@ declare module "react-native-firebase" { * Database. Comparison of the two products hers: * https://firebase.google.com/docs/database/rtdb-vs-firestore */ - firestore(): RNFirebase.firestore.FirestoreModule; + static firestore: { + (): RNFirebase.firestore.Firestore; + } & RNFirebase.firestore.FirestoreStatics; static fabric: { crashlytics(): RNFirebase.crashlytics.Crashlytics; @@ -1078,19 +1080,17 @@ declare module "react-native-firebase" { } namespace firestore { - type FirestoreModule = Firestore & FirestoreStatics; - interface Firestore { batch(): WriteBatch; collection(collectionPath: string): CollectionReference; doc(documentPath: string): DocumentReference; /** NOT SUPPORTED YET */ - enablePersistence(): Promise; + // enablePersistence(): Promise; /** NOT SUPPORTED YET */ - runTransaction(): Promise; + // runTransaction(): Promise; /** NOT SUPPORTED YET */ - settings(): void; + // settings(): void; } interface FirestoreStatics { @@ -1100,11 +1100,10 @@ declare module "react-native-firebase" { enableLogging(enabled: boolean): void; }; - class CollectionReference { - constructor(firestore: Firestore, collectionPath: Path); - get firestore(): Firestore; - get id(): string; - get parent(): DocumentReference; + interface CollectionReference { + readonly firestore: Firestore; + readonly id: string; + readonly parent: DocumentReference; add(data: object): Promise; doc(documentPath?: string): DocumentReference; endAt(snapshot: DocumentSnapshot): Query; @@ -1125,20 +1124,18 @@ declare module "react-native-firebase" { where(fieldPath: string, op: Types.QueryOperator, value: any): Query; } - class DocumentChange { - constructor(firestore: Firestore, nativeData: Types.NativeDocumentChange); - get doc(): DocumentSnapshot; - get newIndex(): number; - get oldIndex(): number; - get type(): string; + interface DocumentChange { + readonly doc: DocumentSnapshot; + readonly newIndex: number; + readonly oldIndex: number; + readonly type: string; } - class DocumentReference { - constructor(firestore: Firestore, documentPath: Path); - get firestore(): Firestore; - get id(): string | null; - get parent(): CollectionReference; - get path(): string; + interface DocumentReference { + readonly firestore: Firestore; + readonly id: string | null; + readonly parent: CollectionReference; + readonly path: string; collection(collectionPath: string): CollectionReference; delete(): Promise; get(): Promise; @@ -1155,9 +1152,8 @@ declare module "react-native-firebase" { 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; } namespace DocumentReference { - // JS code expects this value to be true. interface DocumentListenOptions { - includeMetadataChanges: true; + includeMetadataChanges: boolean; } type ObserverOnNext = (documentSnapshot: DocumentSnapshot) => void; @@ -1168,12 +1164,11 @@ declare module "react-native-firebase" { } } - class DocumentSnapshot { - constructor(firestore: Firestore, nativeData: Types.NativeDocumentSnapshot) - get exists(): boolean; - get id(): string | null; - get metadata(): Types.SnapshotMetadata; - get ref(): DocumentReference; + 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; } @@ -1205,15 +1200,8 @@ declare module "react-native-firebase" { parent(): Path | null; } - class Query { - constructor( - firestore: Firestore, - path: Path, - fieldFilters?: Query.FieldFilter[], - fieldOrders?: Query.FieldOrder[], - queryOptions?: Query.QueryOptions, - ); - get firestore(): Firestore; + interface Query { + readonly firestore: Firestore; endAt(snapshot: DocumentSnapshot): Query; endAt(...varargs: any[]): Query; endBefore(snapshot: DocumentSnapshot): Query; @@ -1221,7 +1209,7 @@ declare module "react-native-firebase" { get(): Promise; limit(limit: number): Query; onSnapshot(onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void; - onSnapshot(observer: Observer): () => 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; @@ -1260,13 +1248,12 @@ declare module "react-native-firebase" { } // The JS code expects at least one of 'includeDocumentMetadataChanges' - // or 'includeQueryMetadataChanges' to be true. This logic is - // encapsulated in QueryListenOptions. + // or 'includeQueryMetadataChanges' to be defined. interface _IncludeDocumentMetadataChanges { - includeDocumentMetadataChanges: true; + includeDocumentMetadataChanges: boolean; } interface _IncludeQueryMetadataChanges { - includeQueryMetadataChanges: true + includeQueryMetadataChanges: boolean; } type QueryListenOptions = _IncludeDocumentMetadataChanges | _IncludeQueryMetadataChanges | (_IncludeDocumentMetadataChanges & _IncludeQueryMetadataChanges); @@ -1278,14 +1265,13 @@ declare module "react-native-firebase" { } } - class QuerySnapshot { - constructor(firestore: Firestore, query: Query, nativeData: QuerySnapshot.NativeData); - get docChanges(): DocumentChange[]; - get docs(): DocumentSnapshot[]; - get empty(): boolean; - get metadata(): Types.SnapshotMetadata; - get query(): Query; - get size(): number; + 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 { @@ -1296,8 +1282,7 @@ declare module "react-native-firebase" { } } - class WriteBatch { - constructor(firestore: Firestore); + interface WriteBatch { commit(): Promise; delete(docRef: DocumentReference): WriteBatch; set(docRef: DocumentReference, data: object, options?: Types.WriteOptions): WriteBatch; From 7f394b56e597f6cfc919cdea941dcafe03218a53 Mon Sep 17 00:00:00 2001 From: Paul Huynh Date: Tue, 30 Jan 2018 10:44:57 +1100 Subject: [PATCH 07/28] Remove implicit 'any' type on QuerySnapshot.forEach() --- lib/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index 8624fbd3..f5be87fd 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1270,7 +1270,7 @@ declare module "react-native-firebase" { readonly metadata: Types.SnapshotMetadata; readonly query: Query; readonly size: number; - forEach(callback: (snapshot: DocumentSnapshot) => any); + forEach(callback: (snapshot: DocumentSnapshot) => any): void; } namespace QuerySnapshot { interface NativeData { From 90195769fdbcdc1edad0ee7ce96a1542d73530f0 Mon Sep 17 00:00:00 2001 From: Paul Huynh Date: Tue, 30 Jan 2018 21:14:35 +1100 Subject: [PATCH 08/28] Fix implicit 'any' and incorrect placement of optional boolean in getIdToken --- lib/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index f5be87fd..3082f7a4 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -583,7 +583,7 @@ declare module "react-native-firebase" { * * @param forceRefresh: boolean - default to false */ - getIdToken(forceRefresh: boolean?): Promise + getIdToken(forceRefresh?: boolean): Promise /** * Link the user with a 3rd party credential provider. @@ -1041,7 +1041,7 @@ declare module "react-native-firebase" { * Returns an unsubscribe function, call the returned function to * unsubscribe from all future events. */ - onLink(listener: (url) => void): () => void; + onLink(listener: (url: string) => void): () => void; } /** From 57b5c8fe881c0e02a2bc860c48a155b6fa8e3977 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 30 Jan 2018 16:43:27 +0000 Subject: [PATCH 09/28] Tweak where the TS validation script is run --- package-lock.json | 6 ++++++ package.json | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 554b27bd..79f119cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8086,6 +8086,12 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "dev": true + }, "ua-parser-js": { "version": "0.7.17", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", diff --git a/package.json b/package.json index ece638dd..d2a9fc6d 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,9 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "build": "genversion lib/version.js && npm run build-lib && npm run build-flow", + "build": "genversion lib/version.js && npm run validate-ts-declarations && npm run build-lib && npm run build-flow", "build-flow": "flow-copy-source -i */__tests__* lib dist", - "build-lib": "npm run validate-ts-declarations && BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", + "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", "clean": "rimraf dist/", "flow": "flow", "format": "eslint --fix ./lib ./tests/src ./tests/lib", From d46024f799dd0270ebb27f79813b9dd13a31878f Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 30 Jan 2018 16:56:01 +0000 Subject: [PATCH 10/28] 3.2.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 79f119cf..65f821d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.2.2", + "version": "3.2.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d2a9fc6d..5c87a60a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.2.2", + "version": "3.2.3", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", From 8060c949a2881cada885849c63c9a4ff93ec5d8c Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 31 Jan 2018 09:09:12 +0000 Subject: [PATCH 11/28] [typings] Add a few missing app, auth and firestore Typescript typings --- lib/index.d.ts | 76 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/lib/index.d.ts b/lib/index.d.ts index b67fc717..4f239a9e 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -37,8 +37,8 @@ declare module "react-native-firebase" { // utils: FirebaseModuleAndStatics; initializeApp(options: Firebase.Options, name: string): App; app(name?: string): App; - apps(): App[]; - SDK_VERSION(): string; + readonly apps: App[]; + readonly SDK_VERSION: string; } namespace Firebase { interface Options { @@ -71,6 +71,8 @@ declare module "react-native-firebase" { // perf(): RNFirebase.perf.Performance; storage(): RNFirebase.storage.Storage; // utils(): RNFirebase.utils.Utils; + readonly name: string; + readonly options: Firebase.Options; } export namespace RNFirebase { @@ -529,13 +531,25 @@ declare module "react-native-firebase" { [key: string]: any; } + type AdditionalUserInfo = { + isNewUser: boolean, + profile?: Object, + providerId: string, + username?: string, + } + + type UserCredential = { + additionalUserInfo?: AdditionalUserInfo, + user: User, + } + type UserInfo = { - displayName?: string, - email?: string, - phoneNumber?: string, - photoURL?: string, - providerId: string, - uid: string, + displayName?: string, + email?: string, + phoneNumber?: string, + photoURL?: string, + providerId: string, + uid: string, } type UpdateProfile = { @@ -543,6 +557,11 @@ declare module "react-native-firebase" { photoURL?: string, } + type UserMetadata = { + creationTime?: string, + lastSignInTime?: string, + } + interface User { /** * The user's display name (if available). @@ -561,6 +580,8 @@ declare module "react-native-firebase" { */ isAnonymous: boolean + metadata: UserMetadata + phoneNumber: string | null /** * - The URL of the user's profile picture (if available). @@ -592,11 +613,17 @@ declare module "react-native-firebase" { */ getIdToken(forceRefresh?: boolean): Promise + getToken(forceRefresh?: boolean): Promise + + linkAndRetrieveDataWithCredential(credential: AuthCredential): Promise + /** * Link the user with a 3rd party credential provider. */ linkWithCredential(credential: AuthCredential): Promise + reauthenticateAndRetrieveDataWithCredential(credential: AuthCredential): Promise + /** * Re-authenticate a user with a third-party authentication provider */ @@ -652,12 +679,11 @@ declare module "react-native-firebase" { } interface ActionCodeInfo { - email: string, - error: string, - fromEmail: string, - verifyEmail: string, - recoverEmail: string, - passwordReset: string + data: { + email?: string, + fromEmail?: string + }, + operation: 'PASSWORD_RESET' | 'VERIFY_EMAIL' | 'RECOVER_EMAIL' } interface ConfirmationResult { @@ -694,7 +720,6 @@ declare module "react-native-firebase" { } namespace auth { - type AuthResult = { authenticated: boolean, user: object | null @@ -706,6 +731,7 @@ declare module "react-native-firebase" { }; interface Auth { + readonly app: App; /** * Returns the current Firebase authentication state. */ @@ -713,7 +739,7 @@ declare module "react-native-firebase" { /** * Returns the currently signed-in user (or null). See the User class documentation for further usage. */ - user: User | null + currentUser: User | null /** * Gets/Sets the language for the app instance @@ -743,12 +769,15 @@ declare module "react-native-firebase" { signOut(): Promise + signInAnonymouslyAndRetrieveData(): Promise + /** * Sign an anonymous user. * If the user has already signed in, that user will be returned */ signInAnonymously(): Promise + createUserAndRetrieveDataWithEmailAndPassword(email: string, password: string): Promise /** * We can create a user by calling the createUserWithEmailAndPassword() function. @@ -756,12 +785,16 @@ declare module "react-native-firebase" { */ createUserWithEmailAndPassword(email: string, password: string): Promise + signInAndRetrieveDataWithEmailAndPassword(email: string, password: string): Promise + /** * To sign a user in with their email and password, use the signInWithEmailAndPassword() function. * It accepts two parameters, the user's email and password: */ signInWithEmailAndPassword(email: string, password: string): Promise + signInAndRetrieveDataWithCustomToken(token: string): Promise + /** * Sign a user in with a self-signed JWT token. * To sign a user using a self-signed custom token, @@ -770,6 +803,8 @@ declare module "react-native-firebase" { */ signInWithCustomToken(token: string): Promise + signInAndRetrieveDataWithCredential(credential: AuthCredential): Promise + /** * Sign in the user with a 3rd party credential provider. * credential requires the following properties: @@ -810,16 +845,13 @@ declare module "react-native-firebase" { */ checkActionCode(code: string): Promise - /** - * Get the currently signed in user - */ - getCurrentUser(): Promise - /** * Returns a list of authentication providers that can be used to sign in a given user (identified by its main email address). */ fetchProvidersForEmail(email: string): Promise> + verifyPasswordResetCode(code: string): Promise + [key: string]: any; } @@ -828,6 +860,7 @@ declare module "react-native-firebase" { PhoneAuthProvider: AuthProvider; GoogleAuthProvider: AuthProvider; GithubAuthProvider: AuthProvider; + OAuthProvider: AuthProvider; TwitterAuthProvider: AuthProvider; FacebookAuthProvider: AuthProvider; PhoneAuthState: { @@ -1079,6 +1112,7 @@ declare module "react-native-firebase" { namespace firestore { interface Firestore { + readonly app: App; batch(): WriteBatch; collection(collectionPath: string): CollectionReference; doc(documentPath: string): DocumentReference; From f0610082de7a81ff795bf15d5bb0a60765bcfb71 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 31 Jan 2018 15:28:20 +0000 Subject: [PATCH 12/28] [admob] Correct name of native module --- lib/modules/admob/index.js | 2 +- lib/types/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 22c26e4b..3a43d503 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -29,7 +29,7 @@ type NativeEvent = { const NATIVE_EVENTS = ['interstitial_event', 'rewarded_video_event']; -export const MODULE_NAME = 'RNFirebaseAdmob'; +export const MODULE_NAME = 'RNFirebaseAdMob'; export const NAMESPACE = 'admob'; export default class AdMob extends ModuleBase { diff --git a/lib/types/index.js b/lib/types/index.js index 0308f711..ac1dc42f 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -48,7 +48,7 @@ export type FirebaseModuleConfig = { }; export type FirebaseModuleName = - | 'RNFirebaseAdmob' + | 'RNFirebaseAdMob' | 'RNFirebaseAnalytics' | 'RNFirebaseAuth' | 'RNFirebaseRemoteConfig' From bddccb0872c83ee4e8db066b07100945e3661830 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 31 Jan 2018 16:05:38 +0000 Subject: [PATCH 13/28] [admob] A few internal fixes --- lib/modules/admob/EventTypes.js | 3 +++ lib/modules/admob/Interstitial.js | 21 +++++++++++++-------- lib/modules/admob/RewardedVideo.js | 18 +++++++++++------- lib/modules/admob/index.js | 4 ++-- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/modules/admob/EventTypes.js b/lib/modules/admob/EventTypes.js index 1afdd1f0..510f62e3 100644 --- a/lib/modules/admob/EventTypes.js +++ b/lib/modules/admob/EventTypes.js @@ -1,3 +1,6 @@ +/** + * @flow + */ export default { onAdLoaded: 'onAdLoaded', onAdOpened: 'onAdOpened', diff --git a/lib/modules/admob/Interstitial.js b/lib/modules/admob/Interstitial.js index 74fcd5d2..a2f4c821 100644 --- a/lib/modules/admob/Interstitial.js +++ b/lib/modules/admob/Interstitial.js @@ -1,18 +1,20 @@ -import { NativeModules, Platform } from 'react-native'; +import { Platform } from 'react-native'; import { statics } from './'; import AdRequest from './AdRequest'; import { SharedEventEmitter } from '../../utils/events'; +import { getNativeModule } from '../../utils/native'; import { nativeToJSError } from '../../utils'; - -const FirebaseAdMob = NativeModules.RNFirebaseAdMob; +import type AdMob from './'; let subscriptions = []; export default class Interstitial { - constructor(admob: Object, adUnit: string) { + _admob: AdMob; + + constructor(admob: AdMob, adUnit: string) { // Interstitials on iOS require a new instance each time if (Platform.OS === 'ios') { - FirebaseAdMob.clearInterstitial(adUnit); + getNativeModule(admob).clearInterstitial(adUnit); } for (let i = 0, len = subscriptions.length; i < len; i++) { @@ -20,7 +22,7 @@ export default class Interstitial { } subscriptions = []; - this.admob = admob; + this._admob = admob; this.adUnit = adUnit; this.loaded = false; SharedEventEmitter.removeAllListeners(`interstitial_${adUnit}`); @@ -67,7 +69,10 @@ export default class Interstitial { adRequest = new AdRequest().addTestDevice().build(); } - return FirebaseAdMob.interstitialLoadAd(this.adUnit, adRequest); + return getNativeModule(this._admob).interstitialLoadAd( + this.adUnit, + adRequest + ); } /** @@ -84,7 +89,7 @@ export default class Interstitial { */ show() { if (this.loaded) { - FirebaseAdMob.interstitialShowAd(this.adUnit); + getNativeModule(this._admob).interstitialShowAd(this.adUnit); } } diff --git a/lib/modules/admob/RewardedVideo.js b/lib/modules/admob/RewardedVideo.js index 601e5a78..f5f6e0db 100644 --- a/lib/modules/admob/RewardedVideo.js +++ b/lib/modules/admob/RewardedVideo.js @@ -1,21 +1,22 @@ -import { NativeModules } from 'react-native'; import { statics } from './'; import AdRequest from './AdRequest'; import { SharedEventEmitter } from '../../utils/events'; +import { getNativeModule } from '../../utils/native'; import { nativeToJSError } from '../../utils'; - -const FirebaseAdMob = NativeModules.RNFirebaseAdMob; +import type AdMob from './'; let subscriptions = []; export default class RewardedVideo { - constructor(admob: Object, adUnit: string) { + _admob: AdMob; + + constructor(admob: AdMob, adUnit: string) { for (let i = 0, len = subscriptions.length; i < len; i++) { subscriptions[i].remove(); } subscriptions = []; - this.admob = admob; + this._admob = admob; this.adUnit = adUnit; this.loaded = false; SharedEventEmitter.removeAllListeners(`rewarded_video_${adUnit}`); @@ -62,7 +63,10 @@ export default class RewardedVideo { adRequest = new AdRequest().addTestDevice().build(); } - return FirebaseAdMob.rewardedVideoLoadAd(this.adUnit, adRequest); + return getNativeModule(this._admob).rewardedVideoLoadAd( + this.adUnit, + adRequest + ); } /** @@ -79,7 +83,7 @@ export default class RewardedVideo { */ show() { if (this.loaded) { - FirebaseAdMob.rewardedVideoShowAd(this.adUnit); + getNativeModule(this._admob).rewardedVideoShowAd(this.adUnit); } } diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 3a43d503..691a35bb 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -61,7 +61,7 @@ export default class AdMob extends ModuleBase { const { adUnit } = event; const jsEventType = `interstitial_${adUnit}`; - if (!SharedEventEmitter.hasListeners(jsEventType)) { + if (SharedEventEmitter.listeners(jsEventType).length === 0) { // TODO } @@ -72,7 +72,7 @@ export default class AdMob extends ModuleBase { const { adUnit } = event; const jsEventType = `rewarded_video_${adUnit}`; - if (!SharedEventEmitter.hasListeners(jsEventType)) { + if (SharedEventEmitter.listeners(jsEventType).length === 0) { // TODO } From 6aef08e14c18531ea792b6de4f6b924990e0fd32 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 1 Feb 2018 08:57:35 +0000 Subject: [PATCH 14/28] [types] Update flowconfig to latest version used by RN --- .flowconfig | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/.flowconfig b/.flowconfig index 87598b62..945dfd07 100644 --- a/.flowconfig +++ b/.flowconfig @@ -3,7 +3,7 @@ .*/*[.]android.js ; Ignore "BUCK" generated dirs -.*/node_modules/react-native/\.buckd/ +/\.buckd/ ; Ignore unexpected extra "@providesModule" .*/node_modules/.*/node_modules/fbjs/.* @@ -16,22 +16,8 @@ ; Ignore polyfills .*/Libraries/polyfills/.* -# React Native problems -.*/node_modules/metro-bundler/src/DeltaBundler/DeltaCalculator.js.flow -.*/node_modules/metro-bundler/src/DeltaBundler/DeltaPatcher.js.flow -.*/node_modules/metro-bundler/src/node-haste/AssetResolutionCache.js.flow -.*/node_modules/metro-bundler/src/node-haste/DependencyGraph.js.flow -#.*/node_modules/react-native/Libraries/Animated/src/nodes/AnimatedStyle.js -#.*/node_modules/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js -#.*/node_modules/react-native/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js -#.*/node_modules/react-native/Libraries/Experimental/SwipeableRow/SwipeableListView.js -#.*/node_modules/react-native/Libraries/Image/ImageBackground.js -#.*/node_modules/react-native/Libraries/Lists/FlatList.js -#.*/node_modules/react-native/Libraries/Lists/MetroListView.js -#.*/node_modules/react-native/Libraries/Lists/SectionList.js -#.*/node_modules/react-native/Libraries/Lists/ViewabilityHelper.js -#.*/node_modules/react-native/Libraries/Lists/VirtualizedList.js -#.*/node_modules/react-native/Libraries/Lists/VirtualizedSectionList.js +; Ignore metro +.*/node_modules/metro/.* # Ignore dist folder .*/dist/.* @@ -44,12 +30,13 @@ [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow/ +node_modules/react-native/flow-github/ [options] -module.system=haste - emoji=true +module.system=haste + munge_underscores=true module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' @@ -63,10 +50,9 @@ suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState -suppress_type=$FixMe -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError suppress_comment=\\(.\\|\n\\)*\\$FlowBug.* From 5675181de2b0596e4e4eca221961ecea0c808b9c Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 1 Feb 2018 09:02:20 +0000 Subject: [PATCH 15/28] [tests] Update build.gradle to match our install instructions --- tests/android/app/build.gradle | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/android/app/build.gradle b/tests/android/app/build.gradle index 0fd2e4f2..39b6b646 100644 --- a/tests/android/app/build.gradle +++ b/tests/android/app/build.gradle @@ -143,11 +143,10 @@ android { project.ext.firebaseVersion = '11.8.0' dependencies { -// compile(project(':react-native-firebase')) { -// transitive = false -// } compile project(':react-native-vector-icons') - compile project(':react-native-firebase') + compile(project(':react-native-firebase')) { + transitive = false + } compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.google.android.gms:play-services-base:$firebaseVersion" compile "com.google.firebase:firebase-ads:$firebaseVersion" From cae07ee979208492784a64578b0c8b3996047d98 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 1 Feb 2018 09:04:06 +0000 Subject: [PATCH 16/28] 3.2.4 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 65f821d5..4e75de32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.2.3", + "version": "3.2.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5c87a60a..32fa8cc1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.2.3", + "version": "3.2.4", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", From 09c30189c4defa604c8771f581f816a449178da0 Mon Sep 17 00:00:00 2001 From: Lipis Date: Thu, 1 Feb 2018 11:56:58 +0100 Subject: [PATCH 17/28] Simplify package.json --- package.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 32fa8cc1..fd9b7925 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", "clean": "rimraf dist/", "flow": "flow", - "format": "eslint --fix ./lib ./tests/src ./tests/lib", + "format": "npm run lint -- --fix", "lint": "eslint ./lib ./tests/src ./tests/lib", "precommit": "lint-staged", "prepublish": "npm run clean && npm run build", @@ -131,11 +131,7 @@ "eslint --fix", "git add" ], - "tests/src/**/*.js": [ - "eslint --fix", - "git add" - ], - "tests/lib/**/*.js": [ + "tests/{src|lib}/**/*.js": [ "eslint --fix", "git add" ] From a74a70c12f505e0cdbe0e48324a3aba7ed46c770 Mon Sep 17 00:00:00 2001 From: Panayiotis Lipiridis Date: Thu, 1 Feb 2018 12:52:39 +0100 Subject: [PATCH 18/28] Prettier json and md files as well --- .github/ISSUE_TEMPLATE.md | 20 ++-- CONTRIBUTING.md | 17 ++- README.md | 59 +++++----- jsconfig.json | 14 +-- package.json | 53 ++------- prettier.config.js | 8 ++ .../AppIcon.appiconset/Contents.json | 104 +++++++++--------- .../Images.xcassets/Contents.json | 8 +- tsconfig.json | 35 +++--- 9 files changed, 141 insertions(+), 177 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index d4d824c0..798e9a31 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -14,27 +14,31 @@ The issue list of this repo is exclusively for bug reports. - - ### Environment -1. Application Target Platform: + +1. Application Target Platform: -2. Development Operating System: + +2. Development Operating System: -3. Build Tools: + +3. Build Tools: -4. React Native version: + +4. React Native version: -5. RNFirebase Version: + +5. RNFirebase Version: -6. Firebase Module: + +6. Firebase Module: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 295cfb85..79b02ec8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,16 +4,17 @@ First, thank you for considering contributing to react-native-firebase! It's people like you that make the open source community such a great community! 😊 -We welcome any type of contribution, not only code. You can help with -- **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open) -- **Marketing**: writing blog posts, howto's, printing stickers, ... -- **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ... -- **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them. -- **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/react-native-firebase). +We welcome any type of contribution, not only code. You can help with + +* **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open) +* **Marketing**: writing blog posts, howto's, printing stickers, ... +* **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ... +* **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them. +* **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/react-native-firebase). ## Your First Contribution -Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). +Working on your first Pull Request? You can learn how from this _free_ series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). ## Submitting code @@ -41,14 +42,12 @@ You can also reach us at oss@invertase.io Thank you to all the people who have already contributed to react-native-firebase! - ### Backers Thank you to all our backers! [[Become a backer](https://opencollective.com/react-native-firebase#backer)] - ### Sponsors Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/react-native-firebase#sponsor)) diff --git a/README.md b/README.md index c96fe625..4c9ad359 100644 --- a/README.md +++ b/README.md @@ -30,43 +30,44 @@ All in all, RNFirebase provides much faster performance (~2x) over the web SDK a --- ## Supported Firebase Features -> The Web SDK column indicates what modules/functionality from the Web SDK are usable within React Native. +> The Web SDK column indicates what modules/functionality from the Web SDK are usable within React Native. > '**?**' indicates partial support -| Firebase Features | v1.x.x | v2.x.x | v3.x.x | v3.1.x | v3.2.x | Web SDK | -| ---------------------- | :---: | :---: | :---: | :---: | :---: | :---: | -| **AdMob** | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Analytics**             | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | -| **App Indexing**           | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| **Authentication** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| _-- Phone Auth_ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | -| **Core** | ❌ |**?**| ✅ | ✅ | ✅ | ✅ | -| _-- Multiple Apps_ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | -| **Cloud Firestore** | ❌ | ❌ | ✅ | ✅ | ✅ |**?**| -| **Cloud Messaging (FCM)** | ✅ | ✅ | ✅ | ✅ | ✅ |**?**| -| **Crashlytics**           | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | -| **Crash Reporting** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Dynamic Links** | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | -| **Invites** | ❌ | ❌ | ❌ |**?**|**?**| ❌ | -| **Performance Monitoring** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Realtime Database** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| _-- Offline Persistence_ | ✅ | ✅ | ✅ | ✅ | ✅ |**?**| -| _-- Transactions_ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| **Remote Config** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Storage** | ✅ | ✅ | ✅ | ✅ | ✅ |**?**| +| Firebase Features | v1.x.x | v2.x.x | v3.x.x | v3.1.x | v3.2.x | Web SDK | +| -------------------------- | :----: | :----: | :----: | :----: | :----: | :-----: | +| **AdMob** | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Analytics**             | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **App Indexing**           | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **Authentication** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _-- Phone Auth_ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | +| **Core** | ❌ | **?** | ✅ | ✅ | ✅ | ✅ | +| _-- Multiple Apps_ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| **Cloud Firestore** | ❌ | ❌ | ✅ | ✅ | ✅ | **?** | +| **Cloud Messaging (FCM)** | ✅ | ✅ | ✅ | ✅ | ✅ | **?** | +| **Crashlytics**           | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | +| **Crash Reporting** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Dynamic Links** | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | +| **Invites** | ❌ | ❌ | ❌ | **?** | **?** | ❌ | +| **Performance Monitoring** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Realtime Database** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _-- Offline Persistence_ | ✅ | ✅ | ✅ | ✅ | ✅ | **?** | +| _-- Transactions_ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **Remote Config** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Storage** | ✅ | ✅ | ✅ | ✅ | ✅ | **?** | --- + ### Supported versions - React Native / Firebase > The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase` -| | 1.X.X | 2.0.X | 2.1.X / 2.2.X | 3.0.X | 3.1.X | 3.2.X | -|------------------------|-------------|-------------|-----------------|----------|-------------|----------| -| React Native | 0.36 - 0.39 | 0.40 - 0.46 | 0.47 + | 0.48 + | 0.48 - 0.49 | 0.50 + | -| Firebase Android SDK | 10.2.0 + | 11.0.0 + | 11.0.0 + | 11.4.2 + | 11.6.0 + | 11.6.2 + | -| Firebase iOS SDK | 3.15.0 + | 4.0.0 + | 4.0.0 + | 4.3.0 + | 4.5.0 + | 4.7.0 + | +| | 1.X.X | 2.0.X | 2.1.X / 2.2.X | 3.0.X | 3.1.X | 3.2.X | +| -------------------- | ----------- | ----------- | ------------- | -------- | ----------- | -------- | +| React Native | 0.36 - 0.39 | 0.40 - 0.46 | 0.47 + | 0.48 + | 0.48 - 0.49 | 0.50 + | +| Firebase Android SDK | 10.2.0 + | 11.0.0 + | 11.0.0 + | 11.4.2 + | 11.6.0 + | 11.6.2 + | +| Firebase iOS SDK | 3.15.0 + | 4.0.0 + | 4.0.0 + | 4.3.0 + | 4.5.0 + | 4.7.0 + | --- @@ -96,7 +97,7 @@ Detailed changes for each release are documented in the [releases notes](https:/ RNFirebase is an Apache-2.0 licensed open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [sponsors](#sponsors) and [backers](#backers). If you'd like to join them, please consider: -- [Become a backer or sponsor on Open Collective](https://opencollective.com/react-native-firebase). +* [Become a backer or sponsor on Open Collective](https://opencollective.com/react-native-firebase). ### Sponsors @@ -131,4 +132,4 @@ Thank you to all the people who have already contributed to RNFirebase! ## License -- See [LICENSE](/LICENSE) +* See [LICENSE](/LICENSE) diff --git a/jsconfig.json b/jsconfig.json index c98b6e08..c11a3996 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,9 +1,7 @@ { - "compilerOptions": { - "allowJs": true, - "allowSyntheticDefaultImports": true - }, - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true + }, + "exclude": ["node_modules"] +} diff --git a/package.json b/package.json index fd9b7925..84184cb9 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", "clean": "rimraf dist/", "flow": "flow", - "format": "npm run lint -- --fix", + "format:assets": "prettier --ignore-path .gitignore --write \"**/*.{json,md}\"", + "format": "npm run format:assets && npm run lint -- --fix", "lint": "eslint ./lib ./tests/src ./tests/lib", "precommit": "lint-staged", "prepublish": "npm run clean && npm run build", @@ -31,45 +32,10 @@ "jest": { "preset": "jest-react-native", "setupFiles": [], - "unmockedModulePathPatterns": [ - "./node_modules/react", - "./node_modules/react-native", - "./node_modules/react-native-mock", - "./node_modules/react-addons-test-utils" - ] + "unmockedModulePathPatterns": ["./node_modules/react", "./node_modules/react-native", "./node_modules/react-native-mock", "./node_modules/react-addons-test-utils"] }, "license": "APACHE-2.0", - "keywords": [ - "react", - "admob", - "auth", - "config", - "digits", - "phone-auth", - "sms", - "firestore", - "cloud-firestore", - "datastore", - "remote-config", - "transactions", - "react-native", - "react-native-firebase", - "firebase", - "fcm", - "apn", - "gcm", - "analytics", - "messaging", - "database", - "android", - "ios", - "crash", - "firestack", - "performance", - "firestore", - "dynamic-links", - "crashlytics" - ], + "keywords": ["react", "admob", "auth", "config", "digits", "phone-auth", "sms", "firestore", "cloud-firestore", "datastore", "remote-config", "transactions", "react-native", "react-native-firebase", "firebase", "fcm", "apn", "gcm", "analytics", "messaging", "database", "android", "ios", "crash", "firestack", "performance", "firestore", "dynamic-links", "crashlytics"], "peerDependencies": { "react": "*", "react-native": ">= 0.48.0", @@ -127,13 +93,8 @@ "logo": "https://opencollective.com/opencollective/logo.txt" }, "lint-staged": { - "lib/**/*.js": [ - "eslint --fix", - "git add" - ], - "tests/{src|lib}/**/*.js": [ - "eslint --fix", - "git add" - ] + "lib/**/*.js": ["eslint --fix", "git add"], + "tests/{src|lib}/**/*.js": ["eslint --fix", "git add"], + "*.{json,md,scss}": ["prettier --write", "git add"] } } diff --git a/prettier.config.js b/prettier.config.js index 87d39087..ee3c8d52 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -1,4 +1,12 @@ module.exports = { trailingComma: 'es5', singleQuote: true, + overrides: [ + { + files: '*.json', + options: { + printWidth: 400, + }, + }, + ], }; diff --git a/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/AppIcon.appiconset/Contents.json index c9202920..664ab6ca 100644 --- a/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,79 +1,79 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "Icon-20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-29.png", - "scale" : "1x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-29.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-29@2x.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "Icon-29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "Icon-40@3x.png", + "scale": "3x" }, { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "Icon-57.png", - "scale" : "1x" + "size": "57x57", + "idiom": "iphone", + "filename": "Icon-57.png", + "scale": "1x" }, { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "Icon-57@2x.png", - "scale" : "2x" + "size": "57x57", + "idiom": "iphone", + "filename": "Icon-57@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "Icon-60@3x.png", + "scale": "3x" }, { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" + "idiom": "ios-marketing", + "size": "1024x1024", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/Contents.json b/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/Contents.json index da4a164c..97a8662e 100644 --- a/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/Contents.json +++ b/tests/ios/ReactNativeFirebaseDemo/Images.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 550ece32..2d1dc9e1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,25 +1,18 @@ { "compilerOptions": { - "target": "es5", - "module": "commonjs", - "jsx": "react", - "sourceMap": true, - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "moduleResolution": "node", - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "lib": [ - "es2015", - "es2016", - "esnext", - "dom" - ] + "target": "es5", + "module": "commonjs", + "jsx": "react", + "sourceMap": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "lib": ["es2015", "es2016", "esnext", "dom"] }, - "files": [ - "./lib/index.d.ts" - ] + "files": ["./lib/index.d.ts"] } From 3cf44c58e8861f1e60c1151c3a01d9660aa62a9a Mon Sep 17 00:00:00 2001 From: Michael Diarmid Date: Wed, 7 Feb 2018 12:43:12 +0000 Subject: [PATCH 19/28] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c9ad359..2b44f3fb 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ License Backers on Open Collective Sponsors on Open Collective - Chat + Chat Follow on Twitter

From 1cdc730e34581645022fa91e761810e1ef430d00 Mon Sep 17 00:00:00 2001 From: Michael Diarmid Date: Wed, 7 Feb 2018 12:48:53 +0000 Subject: [PATCH 20/28] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 798e9a31..20e69af5 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -5,7 +5,7 @@ The issue list of this repo is exclusively for bug reports. 1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests -2) For questions and support please use our Discord chat: https://discord.gg/t6bdqMs or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase +2) For questions and support please use our Discord chat: https://discord.gg/C9aK28N or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase 3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed. --> From 2037b6f7ed79e9a15177a7d64e1b3d70dc910301 Mon Sep 17 00:00:00 2001 From: Michael Diarmid Date: Wed, 7 Feb 2018 12:50:19 +0000 Subject: [PATCH 21/28] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b44f3fb..4c74939e 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ To check out our latest docs, visit [rnfirebase.io](https://rnfirebase.io) ## Questions -For questions and support please use our [Discord chat](https://discord.gg/t6bdqMs) or [Stack Overflow](https://stackoverflow.com/questions/tagged/react-native-firebase). The issue list of this repo is **exclusively** for bug reports. +For questions and support please use our [Discord chat](https://discord.gg/C9aK28N) or [Stack Overflow](https://stackoverflow.com/questions/tagged/react-native-firebase). The issue list of this repo is **exclusively** for bug reports. ## Issues From 7c63ec4ca9c0444b003851c77af8dd0d7946a1c5 Mon Sep 17 00:00:00 2001 From: Michael Diarmid Date: Tue, 13 Feb 2018 14:23:09 +0000 Subject: [PATCH 22/28] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c74939e..2aa8743e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ License Backers on Open Collective Sponsors on Open Collective - Chat + Chat Follow on Twitter

From 1c5c02f6cfa7910f3ccd32316c3033c37152e99b Mon Sep 17 00:00:00 2001 From: Michael Diarmid Date: Tue, 13 Feb 2018 17:53:48 +0000 Subject: [PATCH 23/28] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84184cb9..14d7eca9 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "unmockedModulePathPatterns": ["./node_modules/react", "./node_modules/react-native", "./node_modules/react-native-mock", "./node_modules/react-addons-test-utils"] }, "license": "APACHE-2.0", - "keywords": ["react", "admob", "auth", "config", "digits", "phone-auth", "sms", "firestore", "cloud-firestore", "datastore", "remote-config", "transactions", "react-native", "react-native-firebase", "firebase", "fcm", "apn", "gcm", "analytics", "messaging", "database", "android", "ios", "crash", "firestack", "performance", "firestore", "dynamic-links", "crashlytics"], + "keywords": ["react", "admob", "auth", "config", "digits", "fabric", "phone-auth", "sms", "firestore", "cloud-firestore", "datastore", "remote-config", "transactions", "react-native", "react-native-firebase", "firebase", "fcm", "apn", "gcm", "analytics", "messaging", "database", "android", "ios", "crash", "firestack", "performance", "firestore", "dynamic-links", "crashlytics"], "peerDependencies": { "react": "*", "react-native": ">= 0.48.0", From c8106a3897a1b6865045437d5c33d4136086d1a9 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 14 Feb 2018 10:02:34 +0000 Subject: [PATCH 24/28] [types] Temp rename of file to allow capitalisation --- lib/modules/database/reference-temp.js | 892 +++++++++++++++++++++++++ 1 file changed, 892 insertions(+) create mode 100644 lib/modules/database/reference-temp.js diff --git a/lib/modules/database/reference-temp.js b/lib/modules/database/reference-temp.js new file mode 100644 index 00000000..e9c98e7b --- /dev/null +++ b/lib/modules/database/reference-temp.js @@ -0,0 +1,892 @@ +/** + * @flow + * Database Reference representation wrapper + */ +import Query from './query'; +import DataSnapshot from './DataSnapshot'; +import OnDisconnect from './OnDisconnect'; +import { getLogger } from '../../utils/log'; +import { getNativeModule } from '../../utils/native'; +import ReferenceBase from '../../utils/ReferenceBase'; + +import { + promiseOrCallback, + isFunction, + isObject, + isString, + tryJSONParse, + tryJSONStringify, + generatePushID, +} from '../../utils'; + +import SyncTree from '../../utils/SyncTree'; + +import type Database from './'; +import type { DatabaseModifier, FirebaseError } from '../../types'; + +// track all event registrations by path +let listeners = 0; + +/** + * Enum for event types + * @readonly + * @enum {String} + */ +const ReferenceEventTypes = { + value: 'value', + child_added: 'child_added', + child_removed: 'child_removed', + child_changed: 'child_changed', + child_moved: 'child_moved', +}; + +type DatabaseListener = { + listenerId: number, + eventName: string, + successCallback: Function, + failureCallback?: Function, +}; + +/** + * @typedef {String} ReferenceLocation - Path to location in the database, relative + * to the root reference. Consists of a path where segments are separated by a + * forward slash (/) and ends in a ReferenceKey - except the root location, which + * has no ReferenceKey. + * + * @example + * // root reference location: '/' + * // non-root reference: '/path/to/referenceKey' + */ + +/** + * @typedef {String} ReferenceKey - Identifier for each location that is unique to that + * location, within the scope of its parent. The last part of a ReferenceLocation. + */ + +/** + * Represents a specific location in your Database that can be used for + * reading or writing data. + * + * You can reference the root using firebase.database().ref() or a child location + * by calling firebase.database().ref("child/path"). + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference + * @class Reference + * @extends ReferenceBase + */ +export default class Reference extends ReferenceBase { + _database: Database; + _promise: ?Promise<*>; + _query: Query; + _refListeners: { [listenerId: number]: DatabaseListener }; + + constructor( + database: Database, + path: string, + existingModifiers?: Array + ) { + super(path); + this._promise = null; + this._refListeners = {}; + this._database = database; + this._query = new Query(this, existingModifiers); + getLogger(database).debug('Created new Reference', this._getRefKey()); + } + + /** + * By calling `keepSynced(true)` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, + * it will not be evicted from the persistent disk cache. + * + * @link https://firebase.google.com/docs/reference/android/com/google/firebase/database/Query.html#keepSynced(boolean) + * @param bool + * @returns {*} + */ + keepSynced(bool: boolean): Promise { + return getNativeModule(this._database).keepSynced( + this._getRefKey(), + this.path, + this._query.getModifiers(), + bool + ); + } + + /** + * Writes data to this Database location. + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#set + * @param value + * @param onComplete + * @returns {Promise} + */ + set(value: any, onComplete?: Function): Promise { + return promiseOrCallback( + getNativeModule(this._database).set( + this.path, + this._serializeAnyType(value) + ), + onComplete + ); + } + + /** + * Sets a priority for the data at this Database location. + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#setPriority + * @param priority + * @param onComplete + * @returns {Promise} + */ + setPriority( + priority: string | number | null, + onComplete?: Function + ): Promise { + const _priority = this._serializeAnyType(priority); + + return promiseOrCallback( + getNativeModule(this._database).setPriority(this.path, _priority), + onComplete + ); + } + + /** + * Writes data the Database location. Like set() but also specifies the priority for that data. + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#setWithPriority + * @param value + * @param priority + * @param onComplete + * @returns {Promise} + */ + setWithPriority( + value: any, + priority: string | number | null, + onComplete?: Function + ): Promise { + const _value = this._serializeAnyType(value); + const _priority = this._serializeAnyType(priority); + + return promiseOrCallback( + getNativeModule(this._database).setWithPriority( + this.path, + _value, + _priority + ), + onComplete + ); + } + + /** + * Writes multiple values to the Database at once. + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#update + * @param val + * @param onComplete + * @returns {Promise} + */ + update(val: Object, onComplete?: Function): Promise { + const value = this._serializeObject(val); + + return promiseOrCallback( + getNativeModule(this._database).update(this.path, value), + onComplete + ); + } + + /** + * Removes the data at this Database location. + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#remove + * @param onComplete + * @return {Promise} + */ + remove(onComplete?: Function): Promise { + return promiseOrCallback( + getNativeModule(this._database).remove(this.path), + onComplete + ); + } + + /** + * Atomically modifies the data at this location. + * + * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction + * @param transactionUpdate + * @param onComplete + * @param applyLocally + */ + transaction( + transactionUpdate: Function, + onComplete: ( + error: ?Error, + committed: boolean, + snapshot: ?DataSnapshot + ) => *, + applyLocally: boolean = false + ) { + if (!isFunction(transactionUpdate)) { + return Promise.reject( + new Error('Missing transactionUpdate function argument.') + ); + } + + return new Promise((resolve, reject) => { + const onCompleteWrapper = (error, committed, snapshotData) => { + if (isFunction(onComplete)) { + if (error) { + onComplete(error, committed, null); + } else { + onComplete(null, committed, new DataSnapshot(this, snapshotData)); + } + } + + if (error) return reject(error); + return resolve({ + committed, + snapshot: new DataSnapshot(this, snapshotData), + }); + }; + + // start the transaction natively + this._database._transactionHandler.add( + this, + transactionUpdate, + onCompleteWrapper, + applyLocally + ); + }); + } + + /** + * + * @param eventName + * @param successCallback + * @param cancelOrContext + * @param context + * @returns {Promise.} + */ + once( + eventName: string = 'value', + successCallback: (snapshot: DataSnapshot) => void, + cancelOrContext: (error: FirebaseError) => void, + context?: Object + ) { + return getNativeModule(this._database) + .once(this._getRefKey(), this.path, this._query.getModifiers(), eventName) + .then(({ snapshot }) => { + const _snapshot = new DataSnapshot(this, snapshot); + + if (isFunction(successCallback)) { + if (isObject(cancelOrContext)) + successCallback.bind(cancelOrContext)(_snapshot); + if (context && isObject(context)) + successCallback.bind(context)(_snapshot); + successCallback(_snapshot); + } + + return _snapshot; + }) + .catch(error => { + if (isFunction(cancelOrContext)) return cancelOrContext(error); + return error; + }); + } + + /** + * + * @param value + * @param onComplete + * @returns {*} + */ + push(value: any, onComplete?: Function): Reference | Promise { + if (value === null || value === undefined) { + return 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)) + ); + } + + // otherwise attach promise to 'thenable' reference and return the + // new reference + newRef._setThenable(promise); + return newRef; + } + + /** + * MODIFIERS + */ + + /** + * + * @returns {Reference} + */ + orderByKey(): Reference { + return this.orderBy('orderByKey'); + } + + /** + * + * @returns {Reference} + */ + orderByPriority(): Reference { + return this.orderBy('orderByPriority'); + } + + /** + * + * @returns {Reference} + */ + orderByValue(): Reference { + return this.orderBy('orderByValue'); + } + + /** + * + * @param key + * @returns {Reference} + */ + orderByChild(key: string): Reference { + return this.orderBy('orderByChild', key); + } + + /** + * + * @param name + * @param key + * @returns {Reference} + */ + orderBy(name: string, key?: string): Reference { + const newRef = new Reference( + this._database, + this.path, + this._query.getModifiers() + ); + newRef._query.orderBy(name, key); + return newRef; + } + + /** + * LIMITS + */ + + /** + * + * @param limit + * @returns {Reference} + */ + limitToLast(limit: number): Reference { + return this.limit('limitToLast', limit); + } + + /** + * + * @param limit + * @returns {Reference} + */ + limitToFirst(limit: number): Reference { + return this.limit('limitToFirst', limit); + } + + /** + * + * @param name + * @param limit + * @returns {Reference} + */ + limit(name: string, limit: number): Reference { + const newRef = new Reference( + this._database, + this.path, + this._query.getModifiers() + ); + newRef._query.limit(name, limit); + return newRef; + } + + /** + * FILTERS + */ + + /** + * + * @param value + * @param key + * @returns {Reference} + */ + equalTo(value: any, key?: string): Reference { + return this.filter('equalTo', value, key); + } + + /** + * + * @param value + * @param key + * @returns {Reference} + */ + endAt(value: any, key?: string): Reference { + return this.filter('endAt', value, key); + } + + /** + * + * @param value + * @param key + * @returns {Reference} + */ + startAt(value: any, key?: string): Reference { + return this.filter('startAt', value, key); + } + + /** + * + * @param name + * @param value + * @param key + * @returns {Reference} + */ + filter(name: string, value: any, key?: string): Reference { + const newRef = new Reference( + this._database, + this.path, + this._query.getModifiers() + ); + newRef._query.filter(name, value, key); + return newRef; + } + + /** + * + * @returns {OnDisconnect} + */ + onDisconnect(): OnDisconnect { + return new OnDisconnect(this); + } + + /** + * Creates a Reference to a child of the current Reference, using a relative path. + * No validation is performed on the path to ensure it has a valid format. + * @param {String} path relative to current ref's location + * @returns {!Reference} A new Reference to the path provided, relative to the current + * Reference + * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#child} + */ + child(path: string): Reference { + return new Reference(this._database, `${this.path}/${path}`); + } + + /** + * Return the ref as a path string + * @returns {string} + */ + toString(): string { + return `${this._database.app.options.databaseURL}/${this.path}`; + } + + /** + * Returns whether another Reference represent the same location and are from the + * same instance of firebase.app.App - multiple firebase apps not currently supported. + * @param {Reference} otherRef - Other reference to compare to this one + * @return {Boolean} Whether otherReference is equal to this one + * + * {@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() + ); + } + + /** + * GETTERS + */ + + /** + * The parent location of a Reference, or null for the root Reference. + * @type {Reference} + * + * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#parent} + */ + get parent(): Reference | null { + if (this.path === '/') return null; + return new Reference( + this._database, + this.path.substring(0, this.path.lastIndexOf('/')) + ); + } + + /** + * A reference to itself + * @type {!Reference} + * + * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#ref} + */ + get ref(): Reference { + return this; + } + + /** + * Reference to the root of the database: '/' + * @type {!Reference} + * + * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#root} + */ + get root(): Reference { + return new Reference(this._database, '/'); + } + + /** + * Access then method of promise if set + * @return {*} + */ + 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; + + if (isFunction(fnReject)) { + return fnReject(possibleErr); + } + + throw possibleErr; + } + ); + } + + throw new Error("Cannot read property 'then' of undefined."); + } + + /** + * Access catch method of promise if set + * @return {*} + */ + catch(fnReject: any => any) { + if (isFunction(fnReject) && this._promise && this._promise.catch) { + return this._promise.catch.bind(this._promise)(possibleErr => { + this._promise = null; + return fnReject(possibleErr); + }); + } + + throw new Error("Cannot read property 'catch' of undefined."); + } + + /** + * INTERNALS + */ + + /** + * Generate a unique registration key. + * + * @return {string} + */ + _getRegistrationKey(eventType: string): string { + return `$${this._database.app.name}$/${ + this.path + }$${this._query.queryIdentifier()}$${listeners}$${eventType}`; + } + + /** + * Generate a string that uniquely identifies this + * combination of path and query modifiers + * + * @return {string} + * @private + */ + _getRefKey(): string { + return `$${this._database.app.name}$/${ + this.path + }$${this._query.queryIdentifier()}`; + } + + /** + * Set the promise this 'thenable' reference relates to + * @param promise + * @private + */ + _setThenable(promise: Promise<*>) { + this._promise = promise; + } + + /** + * + * @param obj + * @returns {Object} + * @private + */ + _serializeObject(obj: Object) { + if (!isObject(obj)) return obj; + + // json stringify then parse it calls toString on Objects / Classes + // that support it i.e new Date() becomes a ISO string. + return tryJSONParse(tryJSONStringify(obj)); + } + + /** + * + * @param value + * @returns {*} + * @private + */ + _serializeAnyType(value: any) { + if (isObject(value)) { + return { + type: 'object', + value: this._serializeObject(value), + }; + } + + return { + type: typeof value, + value, + }; + } + + /** + * Register a listener for data changes at the current ref's location. + * The primary method of reading data from a Database. + * + * Listeners can be unbound using {@link off}. + * + * Event Types: + * + * - value: {@link callback}. + * - child_added: {@link callback} + * - child_removed: {@link callback} + * - child_changed: {@link callback} + * - child_moved: {@link callback} + * + * @param {ReferenceEventType} eventType - Type of event to attach a callback for. + * @param {ReferenceEventCallback} callback - Function that will be called + * when the event occurs with the new data. + * @param {cancelCallbackOrContext=} cancelCallbackOrContext - Optional callback that is called + * if the event subscription fails. {@link cancelCallbackOrContext} + * @param {*=} context - Optional object to bind the callbacks to when calling them. + * @returns {ReferenceEventCallback} callback function, unmodified (unbound), for + * convenience if you want to pass an inline function to on() and store it later for + * removing using off(). + * + * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#on} + */ + on( + eventType: string, + callback: DataSnapshot => 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.' + ); + } + + if (!isString(eventType) || !ReferenceEventTypes[eventType]) { + 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.' + ); + } + + if (!isFunction(callback)) { + 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) && + 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 registrationObj = { + eventType, + ref: this, + path: this.path, + key: this._getRefKey(), + appName: this._database.app.name, + eventRegistrationKey, + }; + + SyncTree.addRegistration({ + ...registrationObj, + listener: _context ? callback.bind(_context) : callback, + }); + + if (cancelCallbackOrContext && isFunction(cancelCallbackOrContext)) { + // cancellations have their own separate registration + // as these are one off events, and they're not guaranteed + // to occur either, only happens on failure to register on native + SyncTree.addRegistration({ + ref: this, + once: true, + path: this.path, + key: this._getRefKey(), + appName: this._database.app.name, + eventType: `${eventType}$cancelled`, + eventRegistrationKey: registrationCancellationKey, + listener: _context + ? cancelCallbackOrContext.bind(_context) + : cancelCallbackOrContext, + }); + } + + // initialise the native listener if not already listening + getNativeModule(this._database).on({ + eventType, + path: this.path, + key: this._getRefKey(), + appName: this._database.app.name, + modifiers: this._query.getModifiers(), + hasCancellationCallback: isFunction(cancelCallbackOrContext), + registration: { + eventRegistrationKey, + key: registrationObj.key, + registrationCancellationKey, + }, + }); + + // increment number of listeners - just s short way of making + // every registration unique per .on() call + listeners += 1; + + // return original unbound successCallback for + // the purposes of calling .off(eventType, callback) at a later date + return callback; + } + + /** + * Detaches a callback previously attached with on(). + * + * Detach a callback previously attached with on(). Note that if on() was called + * multiple times with the same eventType and callback, the callback will be called + * multiple times for each event, and off() must be called multiple times to + * remove the callback. Calling off() on a parent listener will not automatically + * remove listeners registered on child nodes, off() must also be called on any + * child listeners to remove the callback. + * + * If a callback is not specified, all callbacks for the specified eventType will be removed. + * Similarly, if no eventType or callback is specified, all callbacks for the Reference will be removed. + * @param eventType + * @param originalCallback + */ + off(eventType?: string = '', originalCallback?: () => any) { + 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) + ); + } + + /* + * 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 (originalCallback && !isFunction(originalCallback)) { + throw new Error( + 'Query.off failed: Function called with 2 arguments, but second optional argument was not a function.' + ); + } + + // Firebase Docs: + // Note that if on() was called + // multiple times with the same eventType and callback, the callback will be called + // multiple times for each event, and off() must be called multiple times to + // remove the callback. + // Remove only a single registration + if (eventType && originalCallback) { + const registration = SyncTree.getOneByPathEventListener( + this.path, + eventType, + originalCallback + ); + if (!registration) return []; + + // remove the paired cancellation registration if any exist + SyncTree.removeListenersForRegistrations([`${registration}$cancelled`]); + + // remove only the first registration to match firebase web sdk + // call multiple times to remove multiple registrations + 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 + ); + + SyncTree.removeListenersForRegistrations( + SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`) + ); + + return SyncTree.removeListenersForRegistrations(registrations); + } +} From 0d348392ebd83ec24bf3e5dce450f4f6ad8d0b47 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 14 Feb 2018 10:05:28 +0000 Subject: [PATCH 25/28] [types] More temp renames for capitalisation --- .../database/{query.js => query-temp.js} | 2 +- lib/modules/database/reference.js | 888 ------------------ 2 files changed, 1 insertion(+), 889 deletions(-) rename lib/modules/database/{query.js => query-temp.js} (97%) delete mode 100644 lib/modules/database/reference.js diff --git a/lib/modules/database/query.js b/lib/modules/database/query-temp.js similarity index 97% rename from lib/modules/database/query.js rename to lib/modules/database/query-temp.js index 974dba85..b58388be 100644 --- a/lib/modules/database/query.js +++ b/lib/modules/database/query-temp.js @@ -5,7 +5,7 @@ import { objectToUniqueId } from '../../utils'; import type { DatabaseModifier } from '../../types'; -import type Reference from './reference'; +import type Reference from './Reference'; // todo doc methods diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js deleted file mode 100644 index b91e6f13..00000000 --- a/lib/modules/database/reference.js +++ /dev/null @@ -1,888 +0,0 @@ -/** - * @flow - * Database Reference representation wrapper - */ -import Query from './query'; -import Snapshot from './snapshot'; -import Disconnect from './disconnect'; -import { getLogger } from '../../utils/log'; -import { getNativeModule } from '../../utils/native'; -import ReferenceBase from '../../utils/ReferenceBase'; - -import { - promiseOrCallback, - isFunction, - isObject, - isString, - tryJSONParse, - tryJSONStringify, - generatePushID, -} from '../../utils'; - -import SyncTree from '../../utils/SyncTree'; - -import type Database from './'; -import type { DatabaseModifier, FirebaseError } from '../../types'; - -// track all event registrations by path -let listeners = 0; - -/** - * Enum for event types - * @readonly - * @enum {String} - */ -const ReferenceEventTypes = { - value: 'value', - child_added: 'child_added', - child_removed: 'child_removed', - child_changed: 'child_changed', - child_moved: 'child_moved', -}; - -type DatabaseListener = { - listenerId: number, - eventName: string, - successCallback: Function, - failureCallback?: Function, -}; - -/** - * @typedef {String} ReferenceLocation - Path to location in the database, relative - * to the root reference. Consists of a path where segments are separated by a - * forward slash (/) and ends in a ReferenceKey - except the root location, which - * has no ReferenceKey. - * - * @example - * // root reference location: '/' - * // non-root reference: '/path/to/referenceKey' - */ - -/** - * @typedef {String} ReferenceKey - Identifier for each location that is unique to that - * location, within the scope of its parent. The last part of a ReferenceLocation. - */ - -/** - * Represents a specific location in your Database that can be used for - * reading or writing data. - * - * You can reference the root using firebase.database().ref() or a child location - * by calling firebase.database().ref("child/path"). - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference - * @class Reference - * @extends ReferenceBase - */ -export default class Reference extends ReferenceBase { - _database: Database; - _promise: ?Promise<*>; - _query: Query; - _refListeners: { [listenerId: number]: DatabaseListener }; - - constructor( - database: Database, - path: string, - existingModifiers?: Array - ) { - super(path); - this._promise = null; - this._refListeners = {}; - this._database = database; - this._query = new Query(this, existingModifiers); - getLogger(database).debug('Created new Reference', this._getRefKey()); - } - - /** - * By calling `keepSynced(true)` on a location, the data for that location will - * automatically be downloaded and kept in sync, even when no listeners are - * attached for that location. Additionally, while a location is kept synced, - * it will not be evicted from the persistent disk cache. - * - * @link https://firebase.google.com/docs/reference/android/com/google/firebase/database/Query.html#keepSynced(boolean) - * @param bool - * @returns {*} - */ - keepSynced(bool: boolean): Promise { - return getNativeModule(this._database).keepSynced( - this._getRefKey(), - this.path, - this._query.getModifiers(), - bool - ); - } - - /** - * Writes data to this Database location. - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#set - * @param value - * @param onComplete - * @returns {Promise} - */ - set(value: any, onComplete?: Function): Promise { - return promiseOrCallback( - getNativeModule(this._database).set( - this.path, - this._serializeAnyType(value) - ), - onComplete - ); - } - - /** - * Sets a priority for the data at this Database location. - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#setPriority - * @param priority - * @param onComplete - * @returns {Promise} - */ - setPriority( - priority: string | number | null, - onComplete?: Function - ): Promise { - const _priority = this._serializeAnyType(priority); - - return promiseOrCallback( - getNativeModule(this._database).setPriority(this.path, _priority), - onComplete - ); - } - - /** - * Writes data the Database location. Like set() but also specifies the priority for that data. - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#setWithPriority - * @param value - * @param priority - * @param onComplete - * @returns {Promise} - */ - setWithPriority( - value: any, - priority: string | number | null, - onComplete?: Function - ): Promise { - const _value = this._serializeAnyType(value); - const _priority = this._serializeAnyType(priority); - - return promiseOrCallback( - getNativeModule(this._database).setWithPriority( - this.path, - _value, - _priority - ), - onComplete - ); - } - - /** - * Writes multiple values to the Database at once. - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#update - * @param val - * @param onComplete - * @returns {Promise} - */ - update(val: Object, onComplete?: Function): Promise { - const value = this._serializeObject(val); - - return promiseOrCallback( - getNativeModule(this._database).update(this.path, value), - onComplete - ); - } - - /** - * Removes the data at this Database location. - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#remove - * @param onComplete - * @return {Promise} - */ - remove(onComplete?: Function): Promise { - return promiseOrCallback( - getNativeModule(this._database).remove(this.path), - onComplete - ); - } - - /** - * Atomically modifies the data at this location. - * - * @link https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction - * @param transactionUpdate - * @param onComplete - * @param applyLocally - */ - transaction( - transactionUpdate: Function, - onComplete: (error: ?Error, committed: boolean, snapshot: ?Snapshot) => *, - applyLocally: boolean = false - ) { - if (!isFunction(transactionUpdate)) { - return Promise.reject( - new Error('Missing transactionUpdate function argument.') - ); - } - - return new Promise((resolve, reject) => { - const onCompleteWrapper = (error, committed, snapshotData) => { - if (isFunction(onComplete)) { - if (error) { - onComplete(error, committed, null); - } else { - onComplete(null, committed, new Snapshot(this, snapshotData)); - } - } - - if (error) return reject(error); - return resolve({ - committed, - snapshot: new Snapshot(this, snapshotData), - }); - }; - - // start the transaction natively - this._database._transactionHandler.add( - this, - transactionUpdate, - onCompleteWrapper, - applyLocally - ); - }); - } - - /** - * - * @param eventName - * @param successCallback - * @param cancelOrContext - * @param context - * @returns {Promise.} - */ - once( - eventName: string = 'value', - successCallback: (snapshot: Object) => void, - cancelOrContext: (error: FirebaseError) => void, - context?: Object - ) { - 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); - successCallback(_snapshot); - } - - return _snapshot; - }) - .catch(error => { - if (isFunction(cancelOrContext)) return cancelOrContext(error); - return error; - }); - } - - /** - * - * @param value - * @param onComplete - * @returns {*} - */ - push(value: any, onComplete?: Function): Reference | Promise { - if (value === null || value === undefined) { - return 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)) - ); - } - - // otherwise attach promise to 'thenable' reference and return the - // new reference - newRef._setThenable(promise); - return newRef; - } - - /** - * MODIFIERS - */ - - /** - * - * @returns {Reference} - */ - orderByKey(): Reference { - return this.orderBy('orderByKey'); - } - - /** - * - * @returns {Reference} - */ - orderByPriority(): Reference { - return this.orderBy('orderByPriority'); - } - - /** - * - * @returns {Reference} - */ - orderByValue(): Reference { - return this.orderBy('orderByValue'); - } - - /** - * - * @param key - * @returns {Reference} - */ - orderByChild(key: string): Reference { - return this.orderBy('orderByChild', key); - } - - /** - * - * @param name - * @param key - * @returns {Reference} - */ - orderBy(name: string, key?: string): Reference { - const newRef = new Reference( - this._database, - this.path, - this._query.getModifiers() - ); - newRef._query.orderBy(name, key); - return newRef; - } - - /** - * LIMITS - */ - - /** - * - * @param limit - * @returns {Reference} - */ - limitToLast(limit: number): Reference { - return this.limit('limitToLast', limit); - } - - /** - * - * @param limit - * @returns {Reference} - */ - limitToFirst(limit: number): Reference { - return this.limit('limitToFirst', limit); - } - - /** - * - * @param name - * @param limit - * @returns {Reference} - */ - limit(name: string, limit: number): Reference { - const newRef = new Reference( - this._database, - this.path, - this._query.getModifiers() - ); - newRef._query.limit(name, limit); - return newRef; - } - - /** - * FILTERS - */ - - /** - * - * @param value - * @param key - * @returns {Reference} - */ - equalTo(value: any, key?: string): Reference { - return this.filter('equalTo', value, key); - } - - /** - * - * @param value - * @param key - * @returns {Reference} - */ - endAt(value: any, key?: string): Reference { - return this.filter('endAt', value, key); - } - - /** - * - * @param value - * @param key - * @returns {Reference} - */ - startAt(value: any, key?: string): Reference { - return this.filter('startAt', value, key); - } - - /** - * - * @param name - * @param value - * @param key - * @returns {Reference} - */ - filter(name: string, value: any, key?: string): Reference { - const newRef = new Reference( - this._database, - this.path, - this._query.getModifiers() - ); - newRef._query.filter(name, value, key); - return newRef; - } - - /** - * - * @returns {Disconnect} - */ - onDisconnect(): Disconnect { - return new Disconnect(this); - } - - /** - * Creates a Reference to a child of the current Reference, using a relative path. - * No validation is performed on the path to ensure it has a valid format. - * @param {String} path relative to current ref's location - * @returns {!Reference} A new Reference to the path provided, relative to the current - * Reference - * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#child} - */ - child(path: string): Reference { - return new Reference(this._database, `${this.path}/${path}`); - } - - /** - * Return the ref as a path string - * @returns {string} - */ - toString(): string { - return `${this._database.app.options.databaseURL}/${this.path}`; - } - - /** - * Returns whether another Reference represent the same location and are from the - * same instance of firebase.app.App - multiple firebase apps not currently supported. - * @param {Reference} otherRef - Other reference to compare to this one - * @return {Boolean} Whether otherReference is equal to this one - * - * {@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() - ); - } - - /** - * GETTERS - */ - - /** - * The parent location of a Reference, or null for the root Reference. - * @type {Reference} - * - * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#parent} - */ - get parent(): Reference | null { - if (this.path === '/') return null; - return new Reference( - this._database, - this.path.substring(0, this.path.lastIndexOf('/')) - ); - } - - /** - * A reference to itself - * @type {!Reference} - * - * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#ref} - */ - get ref(): Reference { - return this; - } - - /** - * Reference to the root of the database: '/' - * @type {!Reference} - * - * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#root} - */ - get root(): Reference { - return new Reference(this._database, '/'); - } - - /** - * Access then method of promise if set - * @return {*} - */ - 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; - - if (isFunction(fnReject)) { - return fnReject(possibleErr); - } - - throw possibleErr; - } - ); - } - - throw new Error("Cannot read property 'then' of undefined."); - } - - /** - * Access catch method of promise if set - * @return {*} - */ - catch(fnReject: any => any) { - if (isFunction(fnReject) && this._promise && this._promise.catch) { - return this._promise.catch.bind(this._promise)(possibleErr => { - this._promise = null; - return fnReject(possibleErr); - }); - } - - throw new Error("Cannot read property 'catch' of undefined."); - } - - /** - * INTERNALS - */ - - /** - * Generate a unique registration key. - * - * @return {string} - */ - _getRegistrationKey(eventType: string): string { - return `$${this._database.app.name}$/${ - this.path - }$${this._query.queryIdentifier()}$${listeners}$${eventType}`; - } - - /** - * Generate a string that uniquely identifies this - * combination of path and query modifiers - * - * @return {string} - * @private - */ - _getRefKey(): string { - return `$${this._database.app.name}$/${ - this.path - }$${this._query.queryIdentifier()}`; - } - - /** - * Set the promise this 'thenable' reference relates to - * @param promise - * @private - */ - _setThenable(promise: Promise<*>) { - this._promise = promise; - } - - /** - * - * @param obj - * @returns {Object} - * @private - */ - _serializeObject(obj: Object) { - if (!isObject(obj)) return obj; - - // json stringify then parse it calls toString on Objects / Classes - // that support it i.e new Date() becomes a ISO string. - return tryJSONParse(tryJSONStringify(obj)); - } - - /** - * - * @param value - * @returns {*} - * @private - */ - _serializeAnyType(value: any) { - if (isObject(value)) { - return { - type: 'object', - value: this._serializeObject(value), - }; - } - - return { - type: typeof value, - value, - }; - } - - /** - * Register a listener for data changes at the current ref's location. - * The primary method of reading data from a Database. - * - * Listeners can be unbound using {@link off}. - * - * Event Types: - * - * - value: {@link callback}. - * - child_added: {@link callback} - * - child_removed: {@link callback} - * - child_changed: {@link callback} - * - child_moved: {@link callback} - * - * @param {ReferenceEventType} eventType - Type of event to attach a callback for. - * @param {ReferenceEventCallback} callback - Function that will be called - * when the event occurs with the new data. - * @param {cancelCallbackOrContext=} cancelCallbackOrContext - Optional callback that is called - * if the event subscription fails. {@link cancelCallbackOrContext} - * @param {*=} context - Optional object to bind the callbacks to when calling them. - * @returns {ReferenceEventCallback} callback function, unmodified (unbound), for - * convenience if you want to pass an inline function to on() and store it later for - * removing using off(). - * - * {@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 { - if (!eventType) { - 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(', ')}"` - ); - } - - if (!callback) { - 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.' - ); - } - - 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.' - ); - } - - const eventRegistrationKey = this._getRegistrationKey(eventType); - const registrationCancellationKey = `${eventRegistrationKey}$cancelled`; - const _context = - cancelCallbackOrContext && !isFunction(cancelCallbackOrContext) - ? cancelCallbackOrContext - : context; - const registrationObj = { - eventType, - ref: this, - path: this.path, - key: this._getRefKey(), - appName: this._database.app.name, - eventRegistrationKey, - }; - - SyncTree.addRegistration({ - ...registrationObj, - listener: _context ? callback.bind(_context) : callback, - }); - - if (cancelCallbackOrContext && isFunction(cancelCallbackOrContext)) { - // cancellations have their own separate registration - // as these are one off events, and they're not guaranteed - // to occur either, only happens on failure to register on native - SyncTree.addRegistration({ - ref: this, - once: true, - path: this.path, - key: this._getRefKey(), - appName: this._database.app.name, - eventType: `${eventType}$cancelled`, - eventRegistrationKey: registrationCancellationKey, - listener: _context - ? cancelCallbackOrContext.bind(_context) - : cancelCallbackOrContext, - }); - } - - // initialise the native listener if not already listening - getNativeModule(this._database).on({ - eventType, - path: this.path, - key: this._getRefKey(), - appName: this._database.app.name, - modifiers: this._query.getModifiers(), - hasCancellationCallback: isFunction(cancelCallbackOrContext), - registration: { - eventRegistrationKey, - key: registrationObj.key, - registrationCancellationKey, - }, - }); - - // increment number of listeners - just s short way of making - // every registration unique per .on() call - listeners += 1; - - // return original unbound successCallback for - // the purposes of calling .off(eventType, callback) at a later date - return callback; - } - - /** - * Detaches a callback previously attached with on(). - * - * Detach a callback previously attached with on(). Note that if on() was called - * multiple times with the same eventType and callback, the callback will be called - * multiple times for each event, and off() must be called multiple times to - * remove the callback. Calling off() on a parent listener will not automatically - * remove listeners registered on child nodes, off() must also be called on any - * child listeners to remove the callback. - * - * If a callback is not specified, all callbacks for the specified eventType will be removed. - * Similarly, if no eventType or callback is specified, all callbacks for the Reference will be removed. - * @param eventType - * @param originalCallback - */ - off(eventType?: string = '', originalCallback?: () => any) { - 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) - ); - } - - /* - * 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 (originalCallback && !isFunction(originalCallback)) { - throw new Error( - 'Query.off failed: Function called with 2 arguments, but second optional argument was not a function.' - ); - } - - // Firebase Docs: - // Note that if on() was called - // multiple times with the same eventType and callback, the callback will be called - // multiple times for each event, and off() must be called multiple times to - // remove the callback. - // Remove only a single registration - if (eventType && originalCallback) { - const registration = SyncTree.getOneByPathEventListener( - this.path, - eventType, - originalCallback - ); - if (!registration) return []; - - // remove the paired cancellation registration if any exist - SyncTree.removeListenersForRegistrations([`${registration}$cancelled`]); - - // remove only the first registration to match firebase web sdk - // call multiple times to remove multiple registrations - 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 - ); - - SyncTree.removeListenersForRegistrations( - SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`) - ); - - return SyncTree.removeListenersForRegistrations(registrations); - } -} From 1199b2bb337b9f0810fd35886b6a3674b088b476 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 14 Feb 2018 10:07:07 +0000 Subject: [PATCH 26/28] [types] Rename back to proper capitalised file name --- lib/modules/database/{query-temp.js => Query.js} | 0 lib/modules/database/{reference-temp.js => Reference.js} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/modules/database/{query-temp.js => Query.js} (100%) rename lib/modules/database/{reference-temp.js => Reference.js} (99%) diff --git a/lib/modules/database/query-temp.js b/lib/modules/database/Query.js similarity index 100% rename from lib/modules/database/query-temp.js rename to lib/modules/database/Query.js diff --git a/lib/modules/database/reference-temp.js b/lib/modules/database/Reference.js similarity index 99% rename from lib/modules/database/reference-temp.js rename to lib/modules/database/Reference.js index e9c98e7b..76e502e7 100644 --- a/lib/modules/database/reference-temp.js +++ b/lib/modules/database/Reference.js @@ -2,7 +2,7 @@ * @flow * Database Reference representation wrapper */ -import Query from './query'; +import Query from './Query'; import DataSnapshot from './DataSnapshot'; import OnDisconnect from './OnDisconnect'; import { getLogger } from '../../utils/log'; From 4e81527246f6c9c9bde2da598bc89ab88d103669 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 14 Feb 2018 13:00:19 +0000 Subject: [PATCH 27/28] [types] Export app, auth, database and firestore types --- lib/index.js | 60 +++++++++++++- lib/modules/admob/index.js | 2 +- lib/modules/analytics/index.js | 2 +- lib/modules/auth/User.js | 10 +-- lib/modules/auth/index.js | 11 +-- lib/modules/auth/types.js | 10 ++- lib/modules/config/index.js | 2 +- lib/modules/core/{firebase-app.js => app.js} | 0 lib/modules/core/firebase.js | 2 +- lib/modules/crash/index.js | 2 +- .../database/{snapshot.js => DataSnapshot.js} | 10 +-- .../{disconnect.js => OnDisconnect.js} | 8 +- lib/modules/database/index.js | 4 +- lib/modules/fabric/crashlytics/index.js | 2 +- lib/modules/firestore/CollectionReference.js | 21 ++--- lib/modules/firestore/DocumentChange.js | 4 +- lib/modules/firestore/DocumentReference.js | 19 ++--- lib/modules/firestore/DocumentSnapshot.js | 14 +--- lib/modules/firestore/Query.js | 22 ++--- lib/modules/firestore/QuerySnapshot.js | 22 ++--- lib/modules/firestore/WriteBatch.js | 12 +-- lib/modules/firestore/index.js | 2 +- lib/modules/firestore/types.js | 54 ++++++++++++ lib/modules/firestore/utils/serialize.js | 16 ++-- lib/modules/links/index.js | 2 +- lib/modules/messaging/index.js | 2 +- lib/modules/perf/index.js | 2 +- lib/modules/storage/index.js | 2 +- lib/modules/utils/index.js | 2 +- lib/types/index.js | 41 ---------- lib/utils/ModuleBase.js | 2 +- lib/utils/SyncTree.js | 8 +- lib/utils/apps.js | 2 +- tests/ios/Podfile.lock | 82 +++++++++---------- 34 files changed, 246 insertions(+), 210 deletions(-) rename lib/modules/core/{firebase-app.js => app.js} (100%) rename lib/modules/database/{snapshot.js => DataSnapshot.js} (95%) rename lib/modules/database/{disconnect.js => OnDisconnect.js} (91%) create mode 100644 lib/modules/firestore/types.js diff --git a/lib/index.js b/lib/index.js index b31d093b..80b57d44 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,6 +3,64 @@ */ import firebase from './modules/core/firebase'; +export default firebase; + +/* + * Export App types + */ +export type { default as App } from './modules/core/app'; + +/* + * Export Auth types + */ +export type { + ActionCodeInfo, + ActionCodeSettings, + AdditionalUserInfo, + AuthCredential, + UserCredential, + UserInfo, + UserMetadata, +} from './modules/auth/types'; +export type { + default as ConfirmationResult, +} from './modules/auth/ConfirmationResult'; export type { default as User } from './modules/auth/User'; -export default firebase; +/* + * Export Database types + */ +export type { default as DataSnapshot } from './modules/database/DataSnapshot'; +export type { default as OnDisconnect } from './modules/database/OnDisconnect'; +export type { default as Reference } from './modules/database/Reference'; +export type { default as DataQuery } from './modules/database/Query'; + +/* + * Export Firestore types + */ +export type { + DocumentListenOptions, + QueryListenOptions, + SetOptions, + SnapshotMetadata, +} from './modules/firestore/types'; +export type { + default as CollectionReference, +} from './modules/firestore/CollectionReference'; +export type { + default as DocumentChange, +} from './modules/firestore/DocumentChange'; +export type { + default as DocumentReference, +} from './modules/firestore/DocumentReference'; +export type { + default as DocumentSnapshot, +} from './modules/firestore/DocumentSnapshot'; +export type { default as FieldPath } from './modules/firestore/FieldPath'; +export type { default as FieldValue } from './modules/firestore/FieldValue'; +export type { default as GeoPoint } from './modules/firestore/GeoPoint'; +export type { default as Query } from './modules/firestore/Query'; +export type { + default as QuerySnapshot, +} from './modules/firestore/QuerySnapshot'; +export type { default as WriteBatch } from './modules/firestore/WriteBatch'; diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 691a35bb..795099a3 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -19,7 +19,7 @@ import EventTypes, { RewardedVideoEventTypes, } from './EventTypes'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; type NativeEvent = { adUnit: string, diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index 373753d3..94588b93 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -5,7 +5,7 @@ import ModuleBase from '../../utils/ModuleBase'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/; diff --git a/lib/modules/auth/User.js b/lib/modules/auth/User.js index cd3b3af6..e509bb94 100644 --- a/lib/modules/auth/User.js +++ b/lib/modules/auth/User.js @@ -11,18 +11,10 @@ import type { AuthCredential, NativeUser, UserCredential, + UserInfo, UserMetadata, } from './types'; -type UserInfo = { - displayName?: string, - email?: string, - phoneNumber?: string, - photoURL?: string, - providerId: string, - uid: string, -}; - type UpdateProfile = { displayName?: string, photoURL?: string, diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 2b18b9df..e7cbe2ed 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -22,26 +22,19 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider'; import PhoneAuthListener from './PhoneAuthListener'; import type { + ActionCodeInfo, ActionCodeSettings, AuthCredential, NativeUser, NativeUserCredential, UserCredential, } from './types'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; type AuthState = { user?: NativeUser, }; -type ActionCodeInfo = { - data: { - email?: string, - fromEmail?: string, - }, - operation: 'PASSWORD_RESET' | 'VERIFY_EMAIL' | 'RECOVER_EMAIL', -}; - const NATIVE_EVENTS = [ 'auth_state_changed', 'auth_id_token_changed', diff --git a/lib/modules/auth/types.js b/lib/modules/auth/types.js index 8f40d619..64655509 100644 --- a/lib/modules/auth/types.js +++ b/lib/modules/auth/types.js @@ -3,6 +3,14 @@ */ import type User from './User'; +export type ActionCodeInfo = { + data: { + email?: string, + fromEmail?: string, + }, + operation: 'PASSWORD_RESET' | 'VERIFY_EMAIL' | 'RECOVER_EMAIL', +}; + export type ActionCodeSettings = { android: { installApp?: boolean, @@ -16,7 +24,7 @@ export type ActionCodeSettings = { url: string, }; -type AdditionalUserInfo = { +export type AdditionalUserInfo = { isNewUser: boolean, profile?: Object, providerId: string, diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index f6535d6d..c07f18c8 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -6,7 +6,7 @@ import { getLogger } from '../../utils/log'; import ModuleBase from '../../utils/ModuleBase'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; type NativeValue = { stringValue?: string, diff --git a/lib/modules/core/firebase-app.js b/lib/modules/core/app.js similarity index 100% rename from lib/modules/core/firebase-app.js rename to lib/modules/core/app.js diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index 13aad29d..c5274d57 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -6,7 +6,7 @@ import { NativeModules } from 'react-native'; import APPS from '../../utils/apps'; import INTERNALS from '../../utils/internals'; -import App from './firebase-app'; +import App from './app'; import VERSION from '../../version'; // module imports diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 314d910a..e18ec36b 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -5,7 +5,7 @@ import ModuleBase from '../../utils/ModuleBase'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; import type { FirebaseError } from '../../types'; export const MODULE_NAME = 'RNFirebaseCrash'; diff --git a/lib/modules/database/snapshot.js b/lib/modules/database/DataSnapshot.js similarity index 95% rename from lib/modules/database/snapshot.js rename to lib/modules/database/DataSnapshot.js index 572ea85b..31597cbf 100644 --- a/lib/modules/database/snapshot.js +++ b/lib/modules/database/DataSnapshot.js @@ -1,15 +1,15 @@ /** * @flow - * Snapshot representation wrapper + * DataSnapshot representation wrapper */ import { isObject, deepGet, deepExists } from './../../utils'; -import type Reference from './reference'; +import type Reference from './Reference'; /** * @class DataSnapshot * @link https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot */ -export default class Snapshot { +export default class DataSnapshot { ref: Reference; key: string; @@ -50,10 +50,10 @@ export default class Snapshot { * @link https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#forEach * @returns {Snapshot} */ - child(path: string): Snapshot { + child(path: string): DataSnapshot { const value = deepGet(this._value, path); const childRef = this.ref.child(path); - return new Snapshot(childRef, { + return new DataSnapshot(childRef, { value, key: childRef.key, exists: value !== null, diff --git a/lib/modules/database/disconnect.js b/lib/modules/database/OnDisconnect.js similarity index 91% rename from lib/modules/database/disconnect.js rename to lib/modules/database/OnDisconnect.js index 3ec940b6..1662b085 100644 --- a/lib/modules/database/disconnect.js +++ b/lib/modules/database/OnDisconnect.js @@ -1,17 +1,17 @@ /** * @flow - * Disconnect representation wrapper + * OnDisconnect representation wrapper */ import { typeOf } from '../../utils'; import { getNativeModule } from '../../utils/native'; import type Database from './'; -import type Reference from './reference'; +import type Reference from './Reference'; /** * @url https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect - * @class Disconnect + * @class OmDisconnect */ -export default class Disconnect { +export default class OnDisconnect { _database: Database; ref: Reference; path: string; diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index c921c565..4967e0e8 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -4,12 +4,12 @@ */ import { NativeModules } from 'react-native'; -import Reference from './reference'; +import Reference from './Reference'; import TransactionHandler from './transaction'; import ModuleBase from '../../utils/ModuleBase'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; const NATIVE_EVENTS = [ 'database_transaction_event', diff --git a/lib/modules/fabric/crashlytics/index.js b/lib/modules/fabric/crashlytics/index.js index b95b9d2d..6b8a4484 100644 --- a/lib/modules/fabric/crashlytics/index.js +++ b/lib/modules/fabric/crashlytics/index.js @@ -5,7 +5,7 @@ import ModuleBase from '../../../utils/ModuleBase'; import { getNativeModule } from '../../../utils/native'; -import type App from '../../core/firebase-app'; +import type App from '../../core/app'; export const MODULE_NAME = 'RNFirebaseCrashlytics'; export const NAMESPACE = 'crashlytics'; diff --git a/lib/modules/firestore/CollectionReference.js b/lib/modules/firestore/CollectionReference.js index 19807680..57e6d2a3 100644 --- a/lib/modules/firestore/CollectionReference.js +++ b/lib/modules/firestore/CollectionReference.js @@ -8,17 +8,13 @@ import { firestoreAutoId } from '../../utils'; import type Firestore from './'; import type { - FirestoreQueryDirection, - FirestoreQueryOperator, -} from '../../types'; + QueryDirection, + QueryListenOptions, + QueryOperator, +} 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 } from './Query'; import type QuerySnapshot from './QuerySnapshot'; /** @@ -95,10 +91,7 @@ export default class CollectionReference { ); } - orderBy( - fieldPath: string | FieldPath, - directionStr?: FirestoreQueryDirection - ): Query { + orderBy(fieldPath: string | FieldPath, directionStr?: QueryDirection): Query { return this._query.orderBy(fieldPath, directionStr); } @@ -110,7 +103,7 @@ export default class CollectionReference { return this._query.startAt(snapshotOrVarArgs); } - where(fieldPath: string, opStr: FirestoreQueryOperator, value: any): Query { + where(fieldPath: string, opStr: QueryOperator, value: any): Query { return this._query.where(fieldPath, opStr, value); } } diff --git a/lib/modules/firestore/DocumentChange.js b/lib/modules/firestore/DocumentChange.js index c0656d0a..6adf9577 100644 --- a/lib/modules/firestore/DocumentChange.js +++ b/lib/modules/firestore/DocumentChange.js @@ -5,7 +5,7 @@ import DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; -import type { FirestoreNativeDocumentChange } from '../../types'; +import type { NativeDocumentChange } from './types'; /** * @class DocumentChange @@ -16,7 +16,7 @@ export default class DocumentChange { _oldIndex: number; _type: string; - constructor(firestore: Firestore, nativeData: FirestoreNativeDocumentChange) { + constructor(firestore: Firestore, nativeData: NativeDocumentChange) { this._document = new DocumentSnapshot(firestore, nativeData.document); this._newIndex = nativeData.newIndex; this._oldIndex = nativeData.oldIndex; diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index 9fb9ac9c..de5bd8d0 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -14,15 +14,12 @@ import { getNativeModule } from '../../utils/native'; import type Firestore from './'; import type { - FirestoreNativeDocumentSnapshot, - FirestoreWriteOptions, -} from '../../types'; + DocumentListenOptions, + NativeDocumentSnapshot, + SetOptions, +} from './types'; import type Path from './Path'; -type DocumentListenOptions = { - includeMetadataChanges: boolean, -}; - type ObserverOnError = Object => void; type ObserverOnNext = DocumentSnapshot => void; @@ -189,9 +186,7 @@ export default class DocumentReference { } const listenerId = firestoreAutoId(); - const listener = ( - nativeDocumentSnapshot: FirestoreNativeDocumentSnapshot - ) => { + const listener = (nativeDocumentSnapshot: NativeDocumentSnapshot) => { const documentSnapshot = new DocumentSnapshot( this.firestore, nativeDocumentSnapshot @@ -227,12 +222,12 @@ export default class DocumentReference { return this._offDocumentSnapshot.bind(this, listenerId, listener); } - set(data: Object, writeOptions?: FirestoreWriteOptions): Promise { + set(data: Object, options?: SetOptions): Promise { const nativeData = buildNativeMap(data); return getNativeModule(this._firestore).documentSet( this.path, nativeData, - writeOptions + options ); } diff --git a/lib/modules/firestore/DocumentSnapshot.js b/lib/modules/firestore/DocumentSnapshot.js index 691c82c4..23e8ef10 100644 --- a/lib/modules/firestore/DocumentSnapshot.js +++ b/lib/modules/firestore/DocumentSnapshot.js @@ -9,10 +9,7 @@ import { isObject } from '../../utils'; import { parseNativeMap } from './utils/serialize'; import type Firestore from './'; -import type { - FirestoreNativeDocumentSnapshot, - FirestoreSnapshotMetadata, -} from '../../types'; +import type { NativeDocumentSnapshot, SnapshotMetadata } from './types'; const extractFieldPathData = (data: Object | void, segments: string[]): any => { if (!data || !isObject(data)) { @@ -30,13 +27,10 @@ const extractFieldPathData = (data: Object | void, segments: string[]): any => { */ export default class DocumentSnapshot { _data: Object | void; - _metadata: FirestoreSnapshotMetadata; + _metadata: SnapshotMetadata; _ref: DocumentReference; - constructor( - firestore: Firestore, - nativeData: FirestoreNativeDocumentSnapshot - ) { + constructor(firestore: Firestore, nativeData: NativeDocumentSnapshot) { this._data = parseNativeMap(firestore, nativeData.data); this._metadata = nativeData.metadata; this._ref = new DocumentReference( @@ -53,7 +47,7 @@ export default class DocumentSnapshot { return this._ref.id; } - get metadata(): FirestoreSnapshotMetadata { + get metadata(): SnapshotMetadata { return this._metadata; } diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 176a1dcc..a162d9ec 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -12,20 +12,21 @@ import { firestoreAutoId, isFunction, isObject } from '../../utils'; import { getNativeModule } from '../../utils/native'; import type Firestore from './'; -import type { - FirestoreQueryDirection, - FirestoreQueryOperator, -} from '../../types'; import type Path from './Path'; +import type { + QueryDirection, + QueryOperator, + QueryListenOptions, +} from './types'; -const DIRECTIONS: { [FirestoreQueryDirection]: string } = { +const DIRECTIONS: { [QueryDirection]: string } = { ASC: 'ASCENDING', asc: 'ASCENDING', DESC: 'DESCENDING', desc: 'DESCENDING', }; -const OPERATORS: { [FirestoreQueryOperator]: string } = { +const OPERATORS: { [QueryOperator]: string } = { '=': 'EQUAL', '==': 'EQUAL', '>': 'GREATER_THAN', @@ -58,11 +59,6 @@ type QueryOptions = { startAt?: any[], }; -export type QueryListenOptions = {| - includeDocumentMetadataChanges: boolean, - includeQueryMetadataChanges: boolean, -|}; - export type ObserverOnError = Object => void; export type ObserverOnNext = QuerySnapshot => void; @@ -320,7 +316,7 @@ export default class Query { orderBy( fieldPath: string | FieldPath, - directionStr?: FirestoreQueryDirection = 'asc' + directionStr?: QueryDirection = 'asc' ): Query { // TODO: Validation // validate.isFieldPath('fieldPath', fieldPath); @@ -379,7 +375,7 @@ export default class Query { where( fieldPath: string | FieldPath, - opStr: FirestoreQueryOperator, + opStr: QueryOperator, value: any ): Query { // TODO: Validation diff --git a/lib/modules/firestore/QuerySnapshot.js b/lib/modules/firestore/QuerySnapshot.js index 3ff070db..d7748cf8 100644 --- a/lib/modules/firestore/QuerySnapshot.js +++ b/lib/modules/firestore/QuerySnapshot.js @@ -7,16 +7,16 @@ import DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; import type { - FirestoreNativeDocumentChange, - FirestoreNativeDocumentSnapshot, - FirestoreSnapshotMetadata, -} from '../../types'; + NativeDocumentChange, + NativeDocumentSnapshot, + SnapshotMetadata, +} from './types'; import type Query from './Query'; -type QuerySnapshotNativeData = { - changes: FirestoreNativeDocumentChange[], - documents: FirestoreNativeDocumentSnapshot[], - metadata: FirestoreSnapshotMetadata, +type NativeQuerySnapshot = { + changes: NativeDocumentChange[], + documents: NativeDocumentSnapshot[], + metadata: SnapshotMetadata, }; /** @@ -25,13 +25,13 @@ type QuerySnapshotNativeData = { export default class QuerySnapshot { _changes: DocumentChange[]; _docs: DocumentSnapshot[]; - _metadata: FirestoreSnapshotMetadata; + _metadata: SnapshotMetadata; _query: Query; constructor( firestore: Firestore, query: Query, - nativeData: QuerySnapshotNativeData + nativeData: NativeQuerySnapshot ) { this._changes = nativeData.changes.map( change => new DocumentChange(firestore, change) @@ -55,7 +55,7 @@ export default class QuerySnapshot { return this._docs.length === 0; } - get metadata(): FirestoreSnapshotMetadata { + get metadata(): SnapshotMetadata { return this._metadata; } diff --git a/lib/modules/firestore/WriteBatch.js b/lib/modules/firestore/WriteBatch.js index afb3dc47..fe4f15a9 100644 --- a/lib/modules/firestore/WriteBatch.js +++ b/lib/modules/firestore/WriteBatch.js @@ -10,7 +10,7 @@ import { getNativeModule } from '../../utils/native'; import type DocumentReference from './DocumentReference'; import type Firestore from './'; -import type { FirestoreWriteOptions } from '../../types'; +import type { SetOptions } from './types'; type DocumentWrite = { data?: Object, @@ -47,19 +47,15 @@ export default class WriteBatch { return this; } - set( - docRef: DocumentReference, - data: Object, - writeOptions?: FirestoreWriteOptions - ) { + set(docRef: DocumentReference, data: Object, options?: SetOptions) { // TODO: Validation // validate.isDocumentReference('docRef', docRef); // validate.isDocument('data', data); - // validate.isOptionalPrecondition('writeOptions', writeOptions); + // validate.isOptionalPrecondition('options', writeOptions); const nativeData = buildNativeMap(data); this._writes.push({ data: nativeData, - options: writeOptions, + options, path: docRef.path, type: 'SET', }); diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index 7b5a185e..d9d02b74 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -16,7 +16,7 @@ import WriteBatch from './WriteBatch'; import INTERNALS from '../../utils/internals'; import type DocumentSnapshot from './DocumentSnapshot'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; import type QuerySnapshot from './QuerySnapshot'; type CollectionSyncEvent = { diff --git a/lib/modules/firestore/types.js b/lib/modules/firestore/types.js new file mode 100644 index 00000000..6ed935dc --- /dev/null +++ b/lib/modules/firestore/types.js @@ -0,0 +1,54 @@ +/* + * @flow + */ + +export type DocumentListenOptions = { + includeMetadataChanges: boolean, +}; + +export type QueryDirection = 'DESC' | 'desc' | 'ASC' | 'asc'; + +export type QueryListenOptions = {| + includeDocumentMetadataChanges: boolean, + includeQueryMetadataChanges: boolean, +|}; + +export type QueryOperator = '<' | '<=' | '=' | '==' | '>' | '>='; + +export type SetOptions = { + merge?: boolean, +}; + +export type SnapshotMetadata = { + fromCache: boolean, + hasPendingWrites: boolean, +}; + +export type NativeDocumentChange = { + document: NativeDocumentSnapshot, + newIndex: number, + oldIndex: number, + type: string, +}; + +export type NativeDocumentSnapshot = { + data: { [string]: NativeTypeMap }, + metadata: SnapshotMetadata, + path: string, +}; + +export type NativeTypeMap = { + type: + | 'array' + | 'boolean' + | 'date' + | 'documentid' + | 'fieldvalue' + | 'geopoint' + | 'null' + | 'number' + | 'object' + | 'reference' + | 'string', + value: any, +}; diff --git a/lib/modules/firestore/utils/serialize.js b/lib/modules/firestore/utils/serialize.js index 24b8f0a5..90e4d936 100644 --- a/lib/modules/firestore/utils/serialize.js +++ b/lib/modules/firestore/utils/serialize.js @@ -13,7 +13,7 @@ import Path from '../Path'; import { typeOf } from '../../../utils'; import type Firestore from '../'; -import type { FirestoreTypeMap } from '../../../types'; +import type { NativeTypeMap } from '../types'; /* * Functions that build up the data needed to represent @@ -21,9 +21,7 @@ import type { FirestoreTypeMap } from '../../../types'; * for transmission to the native side */ -export const buildNativeMap = ( - data: Object -): { [string]: FirestoreTypeMap } => { +export const buildNativeMap = (data: Object): { [string]: NativeTypeMap } => { const nativeData = {}; if (data) { Object.keys(data).forEach(key => { @@ -36,7 +34,7 @@ export const buildNativeMap = ( return nativeData; }; -export const buildNativeArray = (array: Object[]): FirestoreTypeMap[] => { +export const buildNativeArray = (array: Object[]): NativeTypeMap[] => { const nativeArray = []; if (array) { array.forEach(value => { @@ -49,7 +47,7 @@ export const buildNativeArray = (array: Object[]): FirestoreTypeMap[] => { return nativeArray; }; -export const buildTypeMap = (value: any): FirestoreTypeMap | null => { +export const buildTypeMap = (value: any): NativeTypeMap | null => { const type = typeOf(value); if (value === null || value === undefined) { return { @@ -117,7 +115,7 @@ export const buildTypeMap = (value: any): FirestoreTypeMap | null => { export const parseNativeMap = ( firestore: Firestore, - nativeData: { [string]: FirestoreTypeMap } + nativeData: { [string]: NativeTypeMap } ): Object | void => { let data; if (nativeData) { @@ -131,7 +129,7 @@ export const parseNativeMap = ( const parseNativeArray = ( firestore: Firestore, - nativeArray: FirestoreTypeMap[] + nativeArray: NativeTypeMap[] ): any[] => { const array = []; if (nativeArray) { @@ -142,7 +140,7 @@ const parseNativeArray = ( return array; }; -const parseTypeMap = (firestore: Firestore, typeMap: FirestoreTypeMap): any => { +const parseTypeMap = (firestore: Firestore, typeMap: NativeTypeMap): any => { const { type, value } = typeMap; if (type === 'null') { return null; diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index ae475204..28c31879 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -7,7 +7,7 @@ import ModuleBase from '../../utils/ModuleBase'; import { areObjectKeysContainedInOther, isObject, isString } from '../../utils'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; const EVENT_TYPE = { Link: 'dynamic_link_received', diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 4030c5ba..fee50492 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -8,7 +8,7 @@ import ModuleBase from '../../utils/ModuleBase'; import RemoteMessage from './RemoteMessage'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; const EVENT_TYPE = { RefreshToken: 'messaging_token_refreshed', diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 8b0eac38..e394d370 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -6,7 +6,7 @@ import Trace from './Trace'; import ModuleBase from '../../utils/ModuleBase'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; export const MODULE_NAME = 'RNFirebasePerformance'; export const NAMESPACE = 'perf'; diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index f2fce5f2..3803feb9 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -10,7 +10,7 @@ import { getLogger } from '../../utils/log'; import ModuleBase from '../../utils/ModuleBase'; import { getNativeModule } from '../../utils/native'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; const FirebaseStorage = NativeModules.RNFirebaseStorage; diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index f42fbf94..7215f2b1 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -3,7 +3,7 @@ import { NativeModules } from 'react-native'; import INTERNALS from '../../utils/internals'; import { isIOS } from '../../utils'; import ModuleBase from '../../utils/ModuleBase'; -import type App from '../core/firebase-app'; +import type App from '../core/app'; const FirebaseCoreModule = NativeModules.RNFirebase; diff --git a/lib/types/index.js b/lib/types/index.js index ac1dc42f..dd54f999 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -162,47 +162,6 @@ export type FirestoreModule = { nativeModuleExists: boolean, } & FirestoreStatics; -export type FirestoreNativeDocumentChange = { - document: FirestoreNativeDocumentSnapshot, - newIndex: number, - oldIndex: number, - type: string, -}; - -export type FirestoreNativeDocumentSnapshot = { - data: { [string]: FirestoreTypeMap }, - metadata: FirestoreSnapshotMetadata, - path: string, -}; - -export type FirestoreSnapshotMetadata = { - fromCache: boolean, - hasPendingWrites: boolean, -}; - -export type FirestoreQueryDirection = 'DESC' | 'desc' | 'ASC' | 'asc'; -export type FirestoreQueryOperator = '<' | '<=' | '=' | '==' | '>' | '>='; - -export type FirestoreTypeMap = { - type: - | 'array' - | 'boolean' - | 'date' - | 'documentid' - | 'fieldvalue' - | 'geopoint' - | 'null' - | 'number' - | 'object' - | 'reference' - | 'string', - value: any, -}; - -export type FirestoreWriteOptions = { - merge?: boolean, -}; - /* Links types */ export type LinksModule = { diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 8b68c7fd..83dd5f48 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -4,7 +4,7 @@ import { initialiseLogger } from './log'; import { initialiseNativeModule } from './native'; -import type App from '../modules/core/firebase-app'; +import type App from '../modules/core/app'; import type { FirebaseModuleConfig, FirebaseNamespace } from '../types'; export default class ModuleBase { diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index 17de49e3..7c72b7b6 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -4,11 +4,11 @@ import { NativeEventEmitter, NativeModules } from 'react-native'; import { SharedEventEmitter } from './events'; -import DatabaseSnapshot from '../modules/database/snapshot'; -import DatabaseReference from '../modules/database/reference'; +import DataSnapshot from '../modules/database/DataSnapshot'; +import DatabaseReference from '../modules/database/Reference'; import { isString, nativeToJSError } from '../utils'; -type Listener = DatabaseSnapshot => any; +type Listener = DataSnapshot => any; type Registration = { key: string, @@ -83,7 +83,7 @@ class SyncTree { // forward on to users .on(successCallback <-- listener return SharedEventEmitter.emit( eventRegistrationKey, - new DatabaseSnapshot(registration.ref, snapshot), + new DataSnapshot(registration.ref, snapshot), previousChildName ); } diff --git a/lib/utils/apps.js b/lib/utils/apps.js index 7ff37b34..253265e2 100644 --- a/lib/utils/apps.js +++ b/lib/utils/apps.js @@ -2,7 +2,7 @@ * @flow */ import { NativeModules } from 'react-native'; -import App from '../modules/core/firebase-app'; +import App from '../modules/core/app'; import INTERNALS from './internals'; import { isAndroid, isObject, isString } from './'; diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index 480652fa..22babbd1 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -7,44 +7,44 @@ PODS: - BoringSSL/Interface (9.2) - Crashlytics (3.9.3): - Fabric (~> 1.7.2) - - Fabric (1.7.2) - - Firebase/AdMob (4.8.1): + - Fabric (1.7.3) + - Firebase/AdMob (4.8.2): - Firebase/Core - Google-Mobile-Ads-SDK (= 7.27.0) - - Firebase/Auth (4.8.1): + - Firebase/Auth (4.8.2): - Firebase/Core - FirebaseAuth (= 4.4.2) - - Firebase/Core (4.8.1): - - FirebaseAnalytics (= 4.0.7) + - Firebase/Core (4.8.2): + - FirebaseAnalytics (= 4.0.9) - FirebaseCore (= 4.0.14) - - Firebase/Crash (4.8.1): + - Firebase/Crash (4.8.2): - Firebase/Core - FirebaseCrash (= 2.0.2) - - Firebase/Database (4.8.1): + - Firebase/Database (4.8.2): - Firebase/Core - FirebaseDatabase (= 4.1.4) - - Firebase/DynamicLinks (4.8.1): + - Firebase/DynamicLinks (4.8.2): - Firebase/Core - FirebaseDynamicLinks (= 2.3.2) - - Firebase/Firestore (4.8.1): + - Firebase/Firestore (4.8.2): - Firebase/Core - FirebaseFirestore (= 0.10.0) - - Firebase/Messaging (4.8.1): + - Firebase/Messaging (4.8.2): - Firebase/Core - FirebaseMessaging (= 2.0.8) - - Firebase/Performance (4.8.1): + - Firebase/Performance (4.8.2): - Firebase/Core - FirebasePerformance (= 1.1.1) - - Firebase/RemoteConfig (4.8.1): + - Firebase/RemoteConfig (4.8.2): - Firebase/Core - FirebaseRemoteConfig (= 2.1.1) - - Firebase/Storage (4.8.1): + - Firebase/Storage (4.8.2): - Firebase/Core - FirebaseStorage (= 2.1.2) - FirebaseABTesting (1.0.0): - FirebaseCore (~> 4.0) - Protobuf (~> 3.1) - - FirebaseAnalytics (4.0.7): + - FirebaseAnalytics (4.0.9): - FirebaseCore (~> 4.0) - FirebaseInstanceID (~> 2.0) - GoogleToolboxForMac/NSData+zlib (~> 2.1) @@ -114,26 +114,26 @@ PODS: - GoogleToolboxForMac/Defines (= 2.1.3) - GoogleToolboxForMac/NSString+URLArguments (= 2.1.3) - GoogleToolboxForMac/NSString+URLArguments (2.1.3) - - gRPC (1.8.4): - - gRPC-RxLibrary (= 1.8.4) - - gRPC/Main (= 1.8.4) - - gRPC-Core (1.8.4): - - gRPC-Core/Implementation (= 1.8.4) - - gRPC-Core/Interface (= 1.8.4) - - gRPC-Core/Implementation (1.8.4): + - gRPC (1.9.1): + - gRPC-RxLibrary (= 1.9.1) + - gRPC/Main (= 1.9.1) + - gRPC-Core (1.9.1): + - gRPC-Core/Implementation (= 1.9.1) + - gRPC-Core/Interface (= 1.9.1) + - gRPC-Core/Implementation (1.9.1): - BoringSSL (~> 9.0) - - gRPC-Core/Interface (= 1.8.4) + - gRPC-Core/Interface (= 1.9.1) - nanopb (~> 0.3) - - gRPC-Core/Interface (1.8.4) - - gRPC-ProtoRPC (1.8.4): - - gRPC (= 1.8.4) - - gRPC-RxLibrary (= 1.8.4) + - gRPC-Core/Interface (1.9.1) + - gRPC-ProtoRPC (1.9.1): + - gRPC (= 1.9.1) + - gRPC-RxLibrary (= 1.9.1) - Protobuf (~> 3.0) - - gRPC-RxLibrary (1.8.4) - - gRPC/Main (1.8.4): - - gRPC-Core (= 1.8.4) - - gRPC-RxLibrary (= 1.8.4) - - GTMSessionFetcher/Core (1.1.12) + - gRPC-RxLibrary (1.9.1) + - gRPC/Main (1.9.1): + - gRPC-Core (= 1.9.1) + - gRPC-RxLibrary (= 1.9.1) + - GTMSessionFetcher/Core (1.1.13) - leveldb-library (1.20) - nanopb (0.3.8): - nanopb/decode (= 0.3.8) @@ -164,7 +164,7 @@ PODS: - React/Core - React/fishhook - React/RCTBlob - - RNFirebase (3.2.0): + - RNFirebase (3.2.4): - React - yoga (0.52.0.React) @@ -201,10 +201,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: BoringSSL: f3d6b8ce199b9c450a8cfc14895d07a2627fc232 Crashlytics: dbb07d01876c171c5ccbdf7826410380189e452c - Fabric: 9cd6a848efcf1b8b07497e0b6a2e7d336353ba15 - Firebase: 2721056b8885eef90233b03f37be64358d35d262 + Fabric: bb495bb9a7a7677c6d03a1f8b83d95bc49b47e41 + Firebase: 7d3b8cd837ad9fcd391657734c0d56dab8e9a5a3 FirebaseABTesting: d07d0ee833b842d5153549e4c7e2e2cb1c23a3f9 - FirebaseAnalytics: 617afa8c26b57a0c3f11361b248bc9e17bfd8dfd + FirebaseAnalytics: 388b630c15713f5dbf364071f5f3d6077fb52f4e FirebaseAuth: bd2738c5c1e92b108ba5f7f7335908097a4e50bb FirebaseCore: 2e0b98fb2d64ca8140136beff15772bdd14d2dd7 FirebaseCrash: cded0fc566c03651aea606a101bc156085f333ca @@ -219,16 +219,16 @@ SPEC CHECKSUMS: FirebaseSwizzlingUtilities: f1c49a5a372ac852c853722a5891a0a5e2344a6c Google-Mobile-Ads-SDK: 83f7f890e638ce8f1debd440ea363338c9f6be3b GoogleToolboxForMac: 2501e2ad72a52eb3dfe7bd9aee7dad11b858bd20 - gRPC: 572520c17b794362388d5c95396329592a3c199b - gRPC-Core: af0d4f0a53735e335fccc815c50c0a03da695287 - gRPC-ProtoRPC: 6596fde8d27e0718d7de1de1dc99a951d832a809 - gRPC-RxLibrary: f6b1432a667c3354c7b345affed9886c0d4ff549 - GTMSessionFetcher: ebaa1f79a5366922c1735f1566901f50beba23b7 + gRPC: 58828d611419d49da19ad02a60679ffa10a10a87 + gRPC-Core: 66413bf1f2d038a6221bc7bfcbeeaa5a117cee29 + gRPC-ProtoRPC: f29e8b7445e0d3c0311678ab121e6c164da4ca5e + gRPC-RxLibrary: 8e0067bfe8a054022c7a81470baace4f2f633b48 + GTMSessionFetcher: 5bb1eae636127de695590f50e7d248483eb891e6 leveldb-library: '08cba283675b7ed2d99629a4bc5fd052cd2bb6a5' nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03 React: 61a6bdf17a9ff16875c230e6ff278d9de274e16c - RNFirebase: 22b1917fec663706907bc901ed665ac4f8b9bfd6 + RNFirebase: 011e47909cf54070f72d50b8d61eb7b347774d29 yoga: 646606bf554d54a16711f35596178522fbc00480 PODFILE CHECKSUM: 67c98bcb203cb992da590bcab6f690f727653ca5 From 5356b949d755edc1c22ed4f41cc2c6e03af14e32 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 14 Feb 2018 15:10:41 +0000 Subject: [PATCH 28/28] 3.2.5 --- package-lock.json | 2 +- package.json | 57 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4e75de32..2628af9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.2.4", + "version": "3.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 14d7eca9..2fa4c641 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.2.4", + "version": "3.2.5", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", @@ -32,10 +32,46 @@ "jest": { "preset": "jest-react-native", "setupFiles": [], - "unmockedModulePathPatterns": ["./node_modules/react", "./node_modules/react-native", "./node_modules/react-native-mock", "./node_modules/react-addons-test-utils"] + "unmockedModulePathPatterns": [ + "./node_modules/react", + "./node_modules/react-native", + "./node_modules/react-native-mock", + "./node_modules/react-addons-test-utils" + ] }, "license": "APACHE-2.0", - "keywords": ["react", "admob", "auth", "config", "digits", "fabric", "phone-auth", "sms", "firestore", "cloud-firestore", "datastore", "remote-config", "transactions", "react-native", "react-native-firebase", "firebase", "fcm", "apn", "gcm", "analytics", "messaging", "database", "android", "ios", "crash", "firestack", "performance", "firestore", "dynamic-links", "crashlytics"], + "keywords": [ + "react", + "admob", + "auth", + "config", + "digits", + "fabric", + "phone-auth", + "sms", + "firestore", + "cloud-firestore", + "datastore", + "remote-config", + "transactions", + "react-native", + "react-native-firebase", + "firebase", + "fcm", + "apn", + "gcm", + "analytics", + "messaging", + "database", + "android", + "ios", + "crash", + "firestack", + "performance", + "firestore", + "dynamic-links", + "crashlytics" + ], "peerDependencies": { "react": "*", "react-native": ">= 0.48.0", @@ -93,8 +129,17 @@ "logo": "https://opencollective.com/opencollective/logo.txt" }, "lint-staged": { - "lib/**/*.js": ["eslint --fix", "git add"], - "tests/{src|lib}/**/*.js": ["eslint --fix", "git add"], - "*.{json,md,scss}": ["prettier --write", "git add"] + "lib/**/*.js": [ + "eslint --fix", + "git add" + ], + "tests/{src|lib}/**/*.js": [ + "eslint --fix", + "git add" + ], + "*.{json,md,scss}": [ + "prettier --write", + "git add" + ] } }