[types] Get flow type working again; Fix majority of firestore type issues
This commit is contained in:
parent
5c43c88f6a
commit
8bd9684644
|
@ -34,7 +34,13 @@
|
|||
"import/extensions": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"react/jsx-filename-extension": 0
|
||||
"react/jsx-filename-extension": 0,
|
||||
"no-unused-expressions": 0,
|
||||
"flowtype/no-unused-expressions": ['error', {
|
||||
allowShortCircuit: false,
|
||||
allowTernary: false,
|
||||
allowTaggedTemplates: false,
|
||||
}]
|
||||
},
|
||||
"globals": {
|
||||
"__DEV__": true,
|
||||
|
|
|
@ -91,7 +91,7 @@ unsafe.enable_getters_and_setters=true
|
|||
esproposal.class_static_fields=enable
|
||||
esproposal.class_instance_fields=enable
|
||||
|
||||
munge_underscores=true
|
||||
munge_underscores=false
|
||||
|
||||
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
|
||||
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
|
||||
|
@ -105,4 +105,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-4]\\|1[0-9]\\|[0-9
|
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
|
||||
[version]
|
||||
^0.46.0
|
||||
^0.56.0
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* @flow
|
||||
*/
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import INTERNALS from './internals';
|
||||
|
@ -16,10 +19,31 @@ import Firestore, { statics as FirestoreStatics } from './modules/firestore';
|
|||
import Links, { statics as LinksStatics } from './modules/links';
|
||||
import Utils, { statics as UtilsStatics } from './modules/utils';
|
||||
|
||||
import type { FirebaseOptions } from './firebase';
|
||||
|
||||
const FirebaseCoreModule = NativeModules.RNFirebase;
|
||||
|
||||
export default class FirebaseApp {
|
||||
constructor(name: string, options: Object = {}) {
|
||||
_extendedProps: { [string] : boolean };
|
||||
_initialized: boolean;
|
||||
_name: string;
|
||||
_namespaces: { [string]: Object };
|
||||
_nativeInitialized: boolean;
|
||||
_options: FirebaseOptions;
|
||||
admob: () => AdMob;
|
||||
auth: () => Auth;
|
||||
analytics: () => Analytics;
|
||||
config: () => RemoteConfig;
|
||||
crash: () => Crash;
|
||||
database: () => Database;
|
||||
firestore: () => Firestore;
|
||||
links: () => Links;
|
||||
messaging: () => Messaging;
|
||||
perf: () => Performance;
|
||||
storage: () => Storage;
|
||||
utils: () => Utils;
|
||||
|
||||
constructor(name: string, options: FirebaseOptions) {
|
||||
this._name = name;
|
||||
this._namespaces = {};
|
||||
this._options = Object.assign({}, options);
|
||||
|
@ -49,7 +73,7 @@ export default class FirebaseApp {
|
|||
* @param native
|
||||
* @private
|
||||
*/
|
||||
_initializeApp(native = false) {
|
||||
_initializeApp(native: boolean = false) {
|
||||
if (native) {
|
||||
// for apps already initialized natively that
|
||||
// we have info from RN constants
|
||||
|
@ -67,7 +91,7 @@ export default class FirebaseApp {
|
|||
*
|
||||
* @return {*}
|
||||
*/
|
||||
get name() {
|
||||
get name(): string {
|
||||
if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME) {
|
||||
// ios and android firebase sdk's return different
|
||||
// app names - so we just return what the web sdk
|
||||
|
@ -82,7 +106,7 @@ export default class FirebaseApp {
|
|||
*
|
||||
* @return {*}
|
||||
*/
|
||||
get options() {
|
||||
get options(): FirebaseOptions {
|
||||
return Object.assign({}, this._options);
|
||||
}
|
||||
|
||||
|
@ -95,14 +119,14 @@ export default class FirebaseApp {
|
|||
* @param props
|
||||
*/
|
||||
extendApp(props: Object) {
|
||||
if (!isObject(props)) throw new Error(INTERNALS.ERROR_MISSING_ARG('Object', 'extendApp'));
|
||||
if (!isObject(props)) throw new Error(INTERNALS.STRINGS.ERROR_MISSING_ARG('Object', 'extendApp'));
|
||||
const keys = Object.keys(props);
|
||||
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
const key = keys[i];
|
||||
|
||||
if (!this._extendedProps[key] && Object.hasOwnProperty.call(this, key)) {
|
||||
throw new Error(INTERNALS.ERROR_PROTECTED_PROP(key));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_PROTECTED_PROP(key));
|
||||
}
|
||||
|
||||
this[key] = props[key];
|
||||
|
@ -131,7 +155,7 @@ export default class FirebaseApp {
|
|||
*
|
||||
* @return {*}
|
||||
*/
|
||||
onReady(): Promise {
|
||||
onReady(): Promise<FirebaseApp> {
|
||||
if (this._initialized) return Promise.resolve(this);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -144,13 +168,12 @@ export default class FirebaseApp {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param name
|
||||
* @param statics
|
||||
* @param InstanceClass
|
||||
* @return {function()}
|
||||
* @private
|
||||
*/
|
||||
_staticsOrModuleInstance(statics = {}, InstanceClass): Function {
|
||||
_staticsOrModuleInstance(statics: Object = {}, InstanceClass: Class<*>) {
|
||||
const getInstance = () => {
|
||||
const _name = `_${InstanceClass._NAMESPACE}`;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { NativeModules, NativeEventEmitter } from 'react-native';
|
|||
|
||||
import INTERNALS from './internals';
|
||||
import FirebaseApp from './firebase-app';
|
||||
import { isObject, isString, isAndroid } from './utils';
|
||||
import { isObject, isString } from './utils';
|
||||
|
||||
// module imports
|
||||
import AdMob, { statics as AdMobStatics } from './modules/admob';
|
||||
|
@ -24,7 +24,31 @@ import Utils, { statics as UtilsStatics } from './modules/utils';
|
|||
|
||||
const FirebaseCoreModule = NativeModules.RNFirebase;
|
||||
|
||||
export type FirebaseOptions = {
|
||||
apiKey: string,
|
||||
appId: string,
|
||||
databaseURL: string,
|
||||
messagingSenderId: string,
|
||||
projectId: string,
|
||||
storageBucket: string,
|
||||
}
|
||||
|
||||
class FirebaseCore {
|
||||
_nativeEmitters: { [string]: NativeEventEmitter };
|
||||
_nativeSubscriptions: { [string]: boolean };
|
||||
admob: () => AdMob;
|
||||
auth: () => Auth;
|
||||
analytics: () => Analytics;
|
||||
config: () => RemoteConfig;
|
||||
crash: () => Crash;
|
||||
database: () => Database;
|
||||
firestore: () => Firestore;
|
||||
links: () => Links;
|
||||
messaging: () => Messaging;
|
||||
perf: () => Performance;
|
||||
storage: () => Storage;
|
||||
utils: () => Utils;
|
||||
|
||||
constructor() {
|
||||
this._nativeEmitters = {};
|
||||
this._nativeSubscriptions = {};
|
||||
|
@ -71,7 +95,7 @@ class FirebaseCore {
|
|||
* @param name
|
||||
* @return {*}
|
||||
*/
|
||||
initializeApp(options: Object = {}, name: string): FirebaseApp {
|
||||
initializeApp(options: FirebaseOptions, name: string): FirebaseApp {
|
||||
if (name && !isString(name)) {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME);
|
||||
}
|
||||
|
@ -163,7 +187,7 @@ class FirebaseCore {
|
|||
* @param nativeEmitter
|
||||
* @private
|
||||
*/
|
||||
_subscribeForDistribution(eventName, nativeEmitter) {
|
||||
_subscribeForDistribution(eventName: string, nativeEmitter: NativeEventEmitter) {
|
||||
if (!this._nativeSubscriptions[eventName]) {
|
||||
nativeEmitter.addListener(eventName, (event) => {
|
||||
if (event.appName) {
|
||||
|
@ -186,7 +210,7 @@ class FirebaseCore {
|
|||
* @return {function(FirebaseApp=)}
|
||||
* @private
|
||||
*/
|
||||
_appNamespaceOrStatics(statics = {}, InstanceClass): Function {
|
||||
_appNamespaceOrStatics(statics: Object = {}, InstanceClass: Class<*>): Function {
|
||||
const namespace = InstanceClass._NAMESPACE;
|
||||
|
||||
const getNamespace = (app?: FirebaseApp) => {
|
||||
|
@ -215,14 +239,13 @@ class FirebaseCore {
|
|||
* @return {*}
|
||||
* @private
|
||||
*/
|
||||
_getOrSetNativeEmitter(name, nativeModule) {
|
||||
_getOrSetNativeEmitter(name: string, nativeModule: Object): NativeEventEmitter {
|
||||
if (this._nativeEmitters[name]) {
|
||||
return this._nativeEmitters[name];
|
||||
}
|
||||
|
||||
return this._nativeEmitters[name] = new NativeEventEmitter(nativeModule);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new FirebaseCore();
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/**
|
||||
* @flow
|
||||
*/
|
||||
import { Platform, NativeModules } from 'react-native';
|
||||
|
||||
import EventEmitter from './utils/emitter/EventEmitter';
|
||||
import ModuleBase from './utils/ModuleBase';
|
||||
import SyncTree from './utils/SyncTree';
|
||||
|
||||
const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]';
|
||||
|
@ -92,35 +96,35 @@ export default {
|
|||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_MISSING_CB(method) {
|
||||
ERROR_MISSING_CB(method: string) {
|
||||
return `Missing required callback for method ${method}().`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_MISSING_ARG(type, method) {
|
||||
ERROR_MISSING_ARG(type: string, method: string) {
|
||||
return `Missing required argument of type '${type}' for method '${method}()'.`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_MISSING_ARG_NAMED(name, type, method) {
|
||||
ERROR_MISSING_ARG_NAMED(name: string, type: string, method: string) {
|
||||
return `Missing required argument '${name}' of type '${type}' for method '${method}()'.`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_ARG_INVALID_VALUE(name, expected, got) {
|
||||
ERROR_ARG_INVALID_VALUE(name: string, expected: string, got: string) {
|
||||
return `Invalid value for argument '${name}' expected value '${expected}' but got '${got}'.`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_PROTECTED_PROP(name) {
|
||||
ERROR_PROTECTED_PROP(name: string) {
|
||||
return `Property '${name}' is protected and can not be overridden by extendApp.`;
|
||||
},
|
||||
|
||||
|
@ -129,7 +133,7 @@ export default {
|
|||
* @param namespace
|
||||
* @param nativeModule
|
||||
*/
|
||||
ERROR_MISSING_MODULE(namespace, nativeModule) {
|
||||
ERROR_MISSING_MODULE(namespace: string, nativeModule: string) {
|
||||
const snippet = `firebase.${namespace}()`;
|
||||
if (Platform.OS === 'ios') {
|
||||
return `You attempted to use a firebase module that's not installed natively on your iOS project by calling ${snippet}.` +
|
||||
|
@ -151,7 +155,7 @@ export default {
|
|||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_APP_NOT_INIT(appName) {
|
||||
ERROR_APP_NOT_INIT(appName: string) {
|
||||
return `The [${appName}] firebase app has not been initialized!`;
|
||||
},
|
||||
|
||||
|
@ -160,35 +164,35 @@ export default {
|
|||
* @return {string}
|
||||
* @constructor
|
||||
*/
|
||||
ERROR_MISSING_OPT(optName) {
|
||||
ERROR_MISSING_OPT(optName: string) {
|
||||
return `Failed to initialize app. FirebaseOptions missing or invalid '${optName}' property.`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_NOT_APP(namespace) {
|
||||
ERROR_NOT_APP(namespace: string) {
|
||||
return `Invalid FirebaseApp instance passed to firebase.${namespace}(app <--).`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_UNSUPPORTED_CLASS_METHOD(className, method) {
|
||||
ERROR_UNSUPPORTED_CLASS_METHOD(className: string, method: string) {
|
||||
return `${className}.${method}() is unsupported by the native Firebase SDKs.`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_UNSUPPORTED_CLASS_PROPERTY(className, property) {
|
||||
ERROR_UNSUPPORTED_CLASS_PROPERTY(className: string, property: string) {
|
||||
return `${className}.${property} is unsupported by the native Firebase SDKs.`;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_UNSUPPORTED_MODULE_METHOD(module, method) {
|
||||
ERROR_UNSUPPORTED_MODULE_METHOD(module: Class<ModuleBase>, method: string) {
|
||||
return `firebase.${module._NAMESPACE}().${method}() is unsupported by the native Firebase SDKs.`;
|
||||
},
|
||||
|
||||
|
@ -196,7 +200,7 @@ export default {
|
|||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ERROR_PLAY_SERVICES(statusCode) {
|
||||
ERROR_PLAY_SERVICES(statusCode: number) {
|
||||
const knownError = PLAY_SERVICES_CODES[statusCode];
|
||||
let start = 'Google Play Services is required to run firebase services on android but a valid installation was not found on this device.';
|
||||
|
||||
|
@ -208,8 +212,8 @@ export default {
|
|||
return `${start}\r\n\r\n` +
|
||||
'-------------------------\r\n' +
|
||||
(knownError ?
|
||||
`${knownError.code}: ${knownError.message} (code ${statusCode})` :
|
||||
`A specific play store availability reason reason was not available (unknown code: ${statusCode || null})`
|
||||
`${knownError.code}: ${knownError.message} (code ${statusCode})` :
|
||||
`A specific play store availability reason reason was not available (unknown code: ${statusCode})`
|
||||
) +
|
||||
'\r\n-------------------------' +
|
||||
'\r\n\r\n' +
|
||||
|
@ -226,9 +230,9 @@ export default {
|
|||
SyncTree: NativeModules.RNFirebaseDatabase ? new SyncTree(NativeModules.RNFirebaseDatabase) : null,
|
||||
|
||||
// internal utils
|
||||
deleteApp(name: String) {
|
||||
deleteApp(name: String): Promise<boolean> {
|
||||
const app = this.APPS[name];
|
||||
if (!app) return Promise.resolve();
|
||||
if (!app) return Promise.resolve(true);
|
||||
|
||||
// https://firebase.google.com/docs/reference/js/firebase.app.App#delete
|
||||
return app.delete().then(() => {
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
* CollectionReference representation wrapper
|
||||
*/
|
||||
import DocumentReference from './DocumentReference';
|
||||
import Path from './Path';
|
||||
import Query from './Query';
|
||||
import QuerySnapshot from './QuerySnapshot';
|
||||
import Query, { type Direction, type Operator } from './Query';
|
||||
import { firestoreAutoId } from '../../utils';
|
||||
|
||||
import type { Direction, Operator } from './Query';
|
||||
import type Firestore from './';
|
||||
import type Path from './Path';
|
||||
import type QuerySnapshot from './QuerySnapshot';
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class CollectionReference
|
||||
*/
|
||||
export default class CollectionReference {
|
||||
_collectionPath: Path;
|
||||
_firestore: Object;
|
||||
_firestore: Firestore;
|
||||
_query: Query;
|
||||
|
||||
constructor(firestore: Object, collectionPath: Path) {
|
||||
|
@ -71,10 +71,6 @@ export default class CollectionReference {
|
|||
return this._query.limit(n);
|
||||
}
|
||||
|
||||
offset(n: number): Query {
|
||||
return this._query.offset(n);
|
||||
}
|
||||
|
||||
onSnapshot(onNext: () => any, onError?: () => any): () => void {
|
||||
return this._query.onSnapshot(onNext, onError);
|
||||
}
|
||||
|
@ -91,10 +87,6 @@ export default class CollectionReference {
|
|||
return this._query.startAt(fieldValues);
|
||||
}
|
||||
|
||||
stream(): Stream<DocumentSnapshot> {
|
||||
return this._query.stream();
|
||||
}
|
||||
|
||||
where(fieldPath: string, opStr: Operator, value: any): Query {
|
||||
return this._query.where(fieldPath, opStr, value);
|
||||
}
|
||||
|
|
|
@ -2,17 +2,19 @@
|
|||
* @flow
|
||||
* DocumentChange representation wrapper
|
||||
*/
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import DocumentSnapshot, { type DocumentSnapshotNativeData } from './DocumentSnapshot';
|
||||
|
||||
import type Firestore from './';
|
||||
|
||||
|
||||
export type DocumentChangeNativeData = {
|
||||
document: DocumentSnapshot,
|
||||
document: DocumentSnapshotNativeData,
|
||||
newIndex: number,
|
||||
oldIndex: number,
|
||||
type: string,
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class DocumentChange
|
||||
*/
|
||||
export default class DocumentChange {
|
||||
|
@ -21,7 +23,7 @@ export default class DocumentChange {
|
|||
_oldIndex: number;
|
||||
_type: string;
|
||||
|
||||
constructor(firestore: Object, nativeData: DocumentChangeNativeData) {
|
||||
constructor(firestore: Firestore, nativeData: DocumentChangeNativeData) {
|
||||
this._document = new DocumentSnapshot(firestore, nativeData.document);
|
||||
this._newIndex = nativeData.newIndex;
|
||||
this._oldIndex = nativeData.oldIndex;
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
* DocumentReference representation wrapper
|
||||
*/
|
||||
import CollectionReference from './CollectionReference';
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import Path from './Path';
|
||||
import DocumentSnapshot, { type DocumentSnapshotNativeData } from './DocumentSnapshot';
|
||||
import { buildNativeMap } from './utils/serialize';
|
||||
import { firestoreAutoId, isFunction, isObject, isString } from '../../utils';
|
||||
|
||||
import type Firestore from './';
|
||||
import type Path from './Path';
|
||||
|
||||
export type WriteOptions = {
|
||||
merge?: boolean,
|
||||
}
|
||||
|
@ -16,24 +18,27 @@ type DocumentListenOptions = {
|
|||
includeMetadataChanges: boolean,
|
||||
}
|
||||
|
||||
type ObserverOnError = (Object) => void;
|
||||
type ObserverOnNext = (DocumentSnapshot) => void;
|
||||
|
||||
type Observer = {
|
||||
next: (DocumentSnapshot) => void,
|
||||
error?: (Object) => void,
|
||||
error?: ObserverOnError,
|
||||
next: ObserverOnNext,
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class DocumentReference
|
||||
*/
|
||||
export default class DocumentReference {
|
||||
_documentPath: Path;
|
||||
_firestore: Object;
|
||||
_firestore: Firestore;
|
||||
|
||||
constructor(firestore: Object, documentPath: Path) {
|
||||
constructor(firestore: Firestore, documentPath: Path) {
|
||||
this._documentPath = documentPath;
|
||||
this._firestore = firestore;
|
||||
}
|
||||
|
||||
get firestore(): Object {
|
||||
get firestore(): Firestore {
|
||||
return this._firestore;
|
||||
}
|
||||
|
||||
|
@ -43,6 +48,9 @@ export default class DocumentReference {
|
|||
|
||||
get parent(): CollectionReference {
|
||||
const parentPath = this._documentPath.parent();
|
||||
if (!parentPath) {
|
||||
throw new Error('Invalid document path');
|
||||
}
|
||||
return new CollectionReference(this._firestore, parentPath);
|
||||
}
|
||||
|
||||
|
@ -71,9 +79,9 @@ export default class DocumentReference {
|
|||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: DocumentListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void
|
||||
optionsOrObserverOrOnNext: DocumentListenOptions | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
) {
|
||||
let observer = {};
|
||||
let docListenOptions = {};
|
||||
|
@ -125,8 +133,8 @@ export default class DocumentReference {
|
|||
}
|
||||
const listenerId = firestoreAutoId();
|
||||
|
||||
const listener = (nativeDocumentSnapshot) => {
|
||||
const documentSnapshot = new DocumentSnapshot(this, nativeDocumentSnapshot);
|
||||
const listener = (nativeDocumentSnapshot: DocumentSnapshotNativeData) => {
|
||||
const documentSnapshot = new DocumentSnapshot(this.firestore, nativeDocumentSnapshot);
|
||||
observer.next(documentSnapshot);
|
||||
};
|
||||
|
||||
|
@ -158,7 +166,7 @@ export default class DocumentReference {
|
|||
.documentSet(this.path, nativeData, writeOptions);
|
||||
}
|
||||
|
||||
update(...args: Object | string[]): Promise<void> {
|
||||
update(...args: Array<any>): Promise<void> {
|
||||
let data = {};
|
||||
if (args.length === 1) {
|
||||
if (!isObject(args[0])) {
|
||||
|
@ -190,7 +198,7 @@ export default class DocumentReference {
|
|||
* Remove document snapshot listener
|
||||
* @param listener
|
||||
*/
|
||||
_offDocumentSnapshot(listenerId: number, listener: Function) {
|
||||
_offDocumentSnapshot(listenerId: string, listener: Function) {
|
||||
this._firestore.log.info('Removing onDocumentSnapshot listener');
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), listener);
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), listener);
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
*/
|
||||
import DocumentReference from './DocumentReference';
|
||||
import Path from './Path';
|
||||
import { parseNativeMap } from './utils/serialize';
|
||||
import { parseNativeMap, type TypeMap } from './utils/serialize';
|
||||
|
||||
import type Firestore from './';
|
||||
|
||||
export type SnapshotMetadata = {
|
||||
fromCache: boolean,
|
||||
|
@ -12,7 +14,7 @@ export type SnapshotMetadata = {
|
|||
}
|
||||
|
||||
export type DocumentSnapshotNativeData = {
|
||||
data: Object,
|
||||
data: { [string]: TypeMap },
|
||||
metadata: SnapshotMetadata,
|
||||
path: string,
|
||||
}
|
||||
|
@ -21,11 +23,11 @@ export type DocumentSnapshotNativeData = {
|
|||
* @class DocumentSnapshot
|
||||
*/
|
||||
export default class DocumentSnapshot {
|
||||
_data: Object;
|
||||
_data: Object | void;
|
||||
_metadata: SnapshotMetadata;
|
||||
_ref: DocumentReference;
|
||||
|
||||
constructor(firestore: Object, nativeData: DocumentSnapshotNativeData) {
|
||||
constructor(firestore: Firestore, nativeData: DocumentSnapshotNativeData) {
|
||||
this._data = parseNativeMap(firestore, nativeData.data);
|
||||
this._metadata = nativeData.metadata;
|
||||
this._ref = new DocumentReference(firestore, Path.fromName(nativeData.path));
|
||||
|
@ -47,11 +49,11 @@ export default class DocumentSnapshot {
|
|||
return this._ref;
|
||||
}
|
||||
|
||||
data(): Object {
|
||||
data(): Object | void {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
get(fieldPath: string): any {
|
||||
return this._data[fieldPath];
|
||||
return this._data ? this._data[fieldPath] : undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* GeoPoint representation wrapper
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class GeoPoint
|
||||
*/
|
||||
export default class GeoPoint {
|
||||
|
@ -19,11 +19,11 @@ export default class GeoPoint {
|
|||
this._longitude = longitude;
|
||||
}
|
||||
|
||||
get latitude() {
|
||||
get latitude(): number {
|
||||
return this._latitude;
|
||||
}
|
||||
|
||||
get longitude() {
|
||||
get longitude(): number {
|
||||
return this._longitude;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Path representation wrapper
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class Path
|
||||
*/
|
||||
export default class Path {
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
* @flow
|
||||
* Query representation wrapper
|
||||
*/
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import Path from './Path';
|
||||
import QuerySnapshot from './QuerySnapshot';
|
||||
import { buildNativeArray, buildTypeMap } from './utils/serialize';
|
||||
import { firestoreAutoId, isFunction, isObject } from '../../utils';
|
||||
|
||||
import type DocumentSnapshot from './DocumentSnapshot';
|
||||
import type Firestore from './';
|
||||
import type Path from './Path';
|
||||
|
||||
const DIRECTIONS = {
|
||||
ASC: 'ASCENDING',
|
||||
asc: 'ASCENDING',
|
||||
|
@ -54,19 +56,25 @@ type Observer = {
|
|||
error?: (Object) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class Query
|
||||
*/
|
||||
export default class Query {
|
||||
_fieldFilters: FieldFilter[];
|
||||
_fieldOrders: FieldOrder[];
|
||||
_firestore: Object;
|
||||
_firestore: Firestore;
|
||||
_iid: number;
|
||||
_queryOptions: QueryOptions;
|
||||
_referencePath: Path;
|
||||
|
||||
constructor(firestore: Object, path: Path, fieldFilters?: FieldFilter[],
|
||||
fieldOrders?: FieldOrder[], queryOptions?: QueryOptions) {
|
||||
constructor(
|
||||
firestore: Firestore,
|
||||
path: Path,
|
||||
fieldFilters?:
|
||||
FieldFilter[],
|
||||
fieldOrders?: FieldOrder[],
|
||||
queryOptions?: QueryOptions,
|
||||
) {
|
||||
this._fieldFilters = fieldFilters || [];
|
||||
this._fieldOrders = fieldOrders || [];
|
||||
this._firestore = firestore;
|
||||
|
@ -78,24 +86,34 @@ export default class Query {
|
|||
return this._firestore;
|
||||
}
|
||||
|
||||
endAt(...snapshotOrVarArgs: any): Query {
|
||||
endAt(...snapshotOrVarArgs: any[]): Query {
|
||||
const options = {
|
||||
...this._queryOptions,
|
||||
endAt: this._buildOrderByOption(snapshotOrVarArgs),
|
||||
};
|
||||
|
||||
return new Query(this.firestore, this._referencePath, this._fieldFilters,
|
||||
this._fieldOrders, options);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
endBefore(...snapshotOrVarArgs: any): Query {
|
||||
endBefore(...snapshotOrVarArgs: any[]): Query {
|
||||
const options = {
|
||||
...this._queryOptions,
|
||||
endBefore: this._buildOrderByOption(snapshotOrVarArgs),
|
||||
};
|
||||
|
||||
return new Query(this.firestore, this._referencePath, this._fieldFilters,
|
||||
this._fieldOrders, options);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
get(): Promise<QuerySnapshot> {
|
||||
|
@ -117,14 +135,19 @@ export default class Query {
|
|||
...this._queryOptions,
|
||||
limit,
|
||||
};
|
||||
return new Query(this.firestore, this._referencePath, this._fieldFilters,
|
||||
this._fieldOrders, options);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void,
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void,
|
||||
observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void,
|
||||
onError?: (Object) => void,
|
||||
) {
|
||||
let observer = {};
|
||||
let queryListenOptions = {};
|
||||
|
@ -199,12 +222,12 @@ export default class Query {
|
|||
// Add the native listener
|
||||
this._firestore._native
|
||||
.collectionOnSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId,
|
||||
queryListenOptions,
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId,
|
||||
queryListenOptions,
|
||||
);
|
||||
|
||||
// Return an unsubscribe method
|
||||
|
@ -226,28 +249,43 @@ export default class Query {
|
|||
fieldPath,
|
||||
};
|
||||
const combinedOrders = this._fieldOrders.concat(newOrder);
|
||||
return new Query(this.firestore, this._referencePath, this._fieldFilters,
|
||||
combinedOrders, this._queryOptions);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
combinedOrders,
|
||||
this._queryOptions,
|
||||
);
|
||||
}
|
||||
|
||||
startAfter(...snapshotOrVarArgs: any): Query {
|
||||
startAfter(...snapshotOrVarArgs: any[]): Query {
|
||||
const options = {
|
||||
...this._queryOptions,
|
||||
startAfter: this._buildOrderByOption(snapshotOrVarArgs),
|
||||
};
|
||||
|
||||
return new Query(this.firestore, this._referencePath, this._fieldFilters,
|
||||
this._fieldOrders, options);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
startAt(...snapshotOrVarArgs: any): Query {
|
||||
startAt(...snapshotOrVarArgs: any[]): Query {
|
||||
const options = {
|
||||
...this._queryOptions,
|
||||
startAt: this._buildOrderByOption(snapshotOrVarArgs),
|
||||
};
|
||||
|
||||
return new Query(this.firestore, this._referencePath, this._fieldFilters,
|
||||
this._fieldOrders, options);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
where(fieldPath: string, opStr: Operator, value: any): Query {
|
||||
|
@ -261,8 +299,13 @@ export default class Query {
|
|||
value: nativeValue,
|
||||
};
|
||||
const combinedFilters = this._fieldFilters.concat(newFilter);
|
||||
return new Query(this.firestore, this._referencePath, combinedFilters,
|
||||
this._fieldOrders, this._queryOptions);
|
||||
return new Query(
|
||||
this.firestore,
|
||||
this._referencePath,
|
||||
combinedFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,7 +333,7 @@ export default class Query {
|
|||
* Remove query snapshot listener
|
||||
* @param listener
|
||||
*/
|
||||
_offCollectionSnapshot(listenerId: number, listener: Function) {
|
||||
_offCollectionSnapshot(listenerId: string, listener: Function) {
|
||||
this._firestore.log.info('Removing onQuerySnapshot listener');
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), listener);
|
||||
this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), listener);
|
||||
|
@ -300,7 +343,7 @@ export default class Query {
|
|||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId
|
||||
listenerId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
* @flow
|
||||
* QuerySnapshot representation wrapper
|
||||
*/
|
||||
import DocumentChange from './DocumentChange';
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import Query from './Query';
|
||||
import DocumentChange, { type DocumentChangeNativeData } from './DocumentChange';
|
||||
import DocumentSnapshot, { type DocumentSnapshotNativeData, type SnapshotMetadata } from './DocumentSnapshot';
|
||||
|
||||
import type { DocumentChangeNativeData } from './DocumentChange';
|
||||
import type { DocumentSnapshotNativeData, SnapshotMetadata } from './DocumentSnapshot';
|
||||
import type Firestore from './';
|
||||
import type Query from './Query';
|
||||
|
||||
type QuerySnapshotNativeData = {
|
||||
changes: DocumentChangeNativeData[],
|
||||
|
@ -15,7 +14,7 @@ type QuerySnapshotNativeData = {
|
|||
metadata: SnapshotMetadata,
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class QuerySnapshot
|
||||
*/
|
||||
export default class QuerySnapshot {
|
||||
|
@ -24,7 +23,7 @@ export default class QuerySnapshot {
|
|||
_metadata: SnapshotMetadata;
|
||||
_query: Query;
|
||||
|
||||
constructor(firestore: Object, query: Query, nativeData: QuerySnapshotNativeData) {
|
||||
constructor(firestore: Firestore, query: Query, nativeData: QuerySnapshotNativeData) {
|
||||
this._changes = nativeData.changes.map(change => new DocumentChange(firestore, change));
|
||||
this._docs = nativeData.documents.map(doc => new DocumentSnapshot(firestore, doc));
|
||||
this._metadata = nativeData.metadata;
|
||||
|
@ -43,14 +42,14 @@ export default class QuerySnapshot {
|
|||
return this._docs.length === 0;
|
||||
}
|
||||
|
||||
get query(): Query {
|
||||
return this._query;
|
||||
}
|
||||
|
||||
get metadata(): SnapshotMetadata {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
get query(): Query {
|
||||
return this._query;
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._docs.length;
|
||||
}
|
||||
|
@ -59,8 +58,8 @@ export default class QuerySnapshot {
|
|||
// TODO: Validation
|
||||
// validate.isFunction('callback', callback);
|
||||
|
||||
for (const doc of this._docs) {
|
||||
this._docs.forEach((doc) => {
|
||||
callback(doc);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
* @flow
|
||||
* WriteBatch representation wrapper
|
||||
*/
|
||||
import DocumentReference from './DocumentReference';
|
||||
import { buildNativeMap } from './utils/serialize';
|
||||
import { isObject, isString } from '../../utils';
|
||||
|
||||
import type { WriteOptions } from './DocumentReference';
|
||||
import type DocumentReference, { WriteOptions } from './DocumentReference';
|
||||
import type Firestore from './';
|
||||
|
||||
type DocumentWrite = {
|
||||
data?: Object,
|
||||
|
@ -15,14 +15,14 @@ type DocumentWrite = {
|
|||
type: 'DELETE' | 'SET' | 'UPDATE',
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @class WriteBatch
|
||||
*/
|
||||
export default class WriteBatch {
|
||||
_firestore: Object;
|
||||
_firestore: Firestore;
|
||||
_writes: DocumentWrite[];
|
||||
|
||||
constructor(firestore: Object) {
|
||||
constructor(firestore: Firestore) {
|
||||
this._firestore = firestore;
|
||||
this._writes = [];
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ export default class WriteBatch {
|
|||
return this;
|
||||
}
|
||||
|
||||
update(docRef: DocumentReference, ...args: Object | string[]): WriteBatch {
|
||||
update(docRef: DocumentReference, ...args: any[]): WriteBatch {
|
||||
// TODO: Validation
|
||||
// validate.isDocumentReference('docRef', docRef);
|
||||
let data = {};
|
||||
|
|
|
@ -5,13 +5,16 @@
|
|||
import ModuleBase from './../../utils/ModuleBase';
|
||||
import CollectionReference from './CollectionReference';
|
||||
import DocumentReference from './DocumentReference';
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
import FieldValue from './FieldValue';
|
||||
import GeoPoint from './GeoPoint';
|
||||
import Path from './Path';
|
||||
import WriteBatch from './WriteBatch';
|
||||
import INTERNALS from './../../internals';
|
||||
|
||||
import type DocumentSnapshot from './DocumentSnapshot';
|
||||
import type FirebaseApp from '../../firebase-app';
|
||||
import type QuerySnapshot from './QuerySnapshot';
|
||||
|
||||
type CollectionSyncEvent = {
|
||||
appName: string,
|
||||
querySnapshot?: QuerySnapshot,
|
||||
|
@ -37,21 +40,21 @@ export default class Firestore extends ModuleBase {
|
|||
|
||||
_referencePath: Path;
|
||||
|
||||
constructor(firebaseApp: Object, options: Object = {}) {
|
||||
constructor(firebaseApp: FirebaseApp, options: Object = {}) {
|
||||
super(firebaseApp, options, true);
|
||||
this._referencePath = new Path([]);
|
||||
|
||||
this.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
// public event name: onCollectionSnapshot
|
||||
this._getAppEventName('firestore_collection_sync_event'),
|
||||
super._getAppEventName('firestore_collection_sync_event'),
|
||||
this._onCollectionSyncEvent.bind(this),
|
||||
);
|
||||
|
||||
this.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
// public event name: onDocumentSnapshot
|
||||
this._getAppEventName('firestore_document_sync_event'),
|
||||
super._getAppEventName('firestore_document_sync_event'),
|
||||
this._onDocumentSyncEvent.bind(this),
|
||||
);
|
||||
}
|
||||
|
@ -92,15 +95,15 @@ export default class Firestore extends ModuleBase {
|
|||
throw new Error('Persistence is enabled by default on the Firestore SDKs');
|
||||
}
|
||||
|
||||
runTransaction(updateFunction): Promise<any> {
|
||||
runTransaction(): Promise<any> {
|
||||
throw new Error('firebase.firestore().runTransaction() coming soon');
|
||||
}
|
||||
|
||||
setLogLevel(logLevel: 'debug' | 'error' | 'silent'): void {
|
||||
setLogLevel(): void {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Firestore, 'setLogLevel'));
|
||||
}
|
||||
|
||||
settings(settings: Object): void {
|
||||
settings(): void {
|
||||
throw new Error('firebase.firestore().settings() coming soon');
|
||||
}
|
||||
|
||||
|
@ -115,9 +118,9 @@ export default class Firestore extends ModuleBase {
|
|||
*/
|
||||
_onCollectionSyncEvent(event: CollectionSyncEvent) {
|
||||
if (event.error) {
|
||||
this.emit(this._getAppEventName(`onQuerySnapshotError:${event.listenerId}`), event.error);
|
||||
this.emit(super._getAppEventName(`onQuerySnapshotError:${event.listenerId}`), event.error);
|
||||
} else {
|
||||
this.emit(this._getAppEventName(`onQuerySnapshot:${event.listenerId}`), event.querySnapshot);
|
||||
this.emit(super._getAppEventName(`onQuerySnapshot:${event.listenerId}`), event.querySnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,9 +131,9 @@ export default class Firestore extends ModuleBase {
|
|||
*/
|
||||
_onDocumentSyncEvent(event: DocumentSyncEvent) {
|
||||
if (event.error) {
|
||||
this.emit(this._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error);
|
||||
this.emit(super._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error);
|
||||
} else {
|
||||
this.emit(this._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot);
|
||||
this.emit(super._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// @flow
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import DocumentReference from '../DocumentReference';
|
||||
import { DELETE_FIELD_VALUE, SERVER_TIMESTAMP_FIELD_VALUE } from '../FieldValue';
|
||||
|
@ -6,8 +8,10 @@ import GeoPoint from '../GeoPoint';
|
|||
import Path from '../Path';
|
||||
import { typeOf } from '../../../utils';
|
||||
|
||||
type TypeMap = {
|
||||
type: 'array' | 'boolean' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string',
|
||||
import type Firestore from '../';
|
||||
|
||||
export type TypeMap = {
|
||||
type: 'array' | 'boolean' | 'date' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string',
|
||||
value: any,
|
||||
}
|
||||
|
||||
|
@ -17,65 +21,86 @@ type TypeMap = {
|
|||
* for transmission to the native side
|
||||
*/
|
||||
|
||||
export const buildNativeMap = (data: Object): Object => {
|
||||
export const buildNativeMap = (data: Object): { [string]: TypeMap } => {
|
||||
const nativeData = {};
|
||||
if (data) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
nativeData[key] = buildTypeMap(data[key]);
|
||||
const typeMap = buildTypeMap(data[key]);
|
||||
if (typeMap) {
|
||||
nativeData[key] = typeMap;
|
||||
}
|
||||
});
|
||||
}
|
||||
return nativeData;
|
||||
};
|
||||
|
||||
export const buildNativeArray = (array: Object[]): any[] => {
|
||||
export const buildNativeArray = (array: Object[]): TypeMap[] => {
|
||||
const nativeArray = [];
|
||||
if (array) {
|
||||
array.forEach((value) => {
|
||||
nativeArray.push(buildTypeMap(value));
|
||||
const typeMap = buildTypeMap(value);
|
||||
if (typeMap) {
|
||||
nativeArray.push(typeMap);
|
||||
}
|
||||
});
|
||||
}
|
||||
return nativeArray;
|
||||
};
|
||||
|
||||
export const buildTypeMap = (value: any): any => {
|
||||
const typeMap = {};
|
||||
export const buildTypeMap = (value: any): TypeMap | null => {
|
||||
const type = typeOf(value);
|
||||
if (value === null || value === undefined) {
|
||||
typeMap.type = 'null';
|
||||
typeMap.value = null;
|
||||
return {
|
||||
type: 'null',
|
||||
value: null,
|
||||
};
|
||||
} else if (value === DELETE_FIELD_VALUE) {
|
||||
typeMap.type = 'fieldvalue';
|
||||
typeMap.value = 'delete';
|
||||
return {
|
||||
type: 'fieldvalue',
|
||||
value: 'delete',
|
||||
};
|
||||
} else if (value === SERVER_TIMESTAMP_FIELD_VALUE) {
|
||||
typeMap.type = 'fieldvalue';
|
||||
typeMap.value = 'timestamp';
|
||||
return {
|
||||
type: 'fieldvalue',
|
||||
value: 'timestamp',
|
||||
};
|
||||
} else if (type === 'boolean' || type === 'number' || type === 'string') {
|
||||
typeMap.type = type;
|
||||
typeMap.value = value;
|
||||
return {
|
||||
type,
|
||||
value,
|
||||
};
|
||||
} else if (type === 'array') {
|
||||
typeMap.type = type;
|
||||
typeMap.value = buildNativeArray(value);
|
||||
return {
|
||||
type,
|
||||
value: buildNativeArray(value),
|
||||
};
|
||||
} else if (type === 'object') {
|
||||
if (value instanceof DocumentReference) {
|
||||
typeMap.type = 'reference';
|
||||
typeMap.value = value.path;
|
||||
return {
|
||||
type: 'reference',
|
||||
value: value.path,
|
||||
};
|
||||
} else if (value instanceof GeoPoint) {
|
||||
typeMap.type = 'geopoint';
|
||||
typeMap.value = {
|
||||
latitude: value.latitude,
|
||||
longitude: value.longitude,
|
||||
return {
|
||||
type: 'geopoint',
|
||||
value: {
|
||||
latitude: value.latitude,
|
||||
longitude: value.longitude,
|
||||
},
|
||||
};
|
||||
} else if (value instanceof Date) {
|
||||
typeMap.type = 'date';
|
||||
typeMap.value = value.getTime();
|
||||
} else {
|
||||
typeMap.type = 'object';
|
||||
typeMap.value = buildNativeMap(value);
|
||||
return {
|
||||
type: 'date',
|
||||
value: value.getTime(),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
console.warn(`Unknown data type received ${type}`);
|
||||
return {
|
||||
type: 'object',
|
||||
value: buildNativeMap(value),
|
||||
};
|
||||
}
|
||||
return typeMap;
|
||||
console.warn(`Unknown data type received ${type}`);
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -83,7 +108,7 @@ export const buildTypeMap = (value: any): any => {
|
|||
* side and converts to the correct Firestore JS types
|
||||
*/
|
||||
|
||||
export const parseNativeMap = (firestore: Object, nativeData: Object): Object => {
|
||||
export const parseNativeMap = (firestore: Firestore, nativeData: { [string]: TypeMap }): Object | void => {
|
||||
let data;
|
||||
if (nativeData) {
|
||||
data = {};
|
||||
|
@ -94,7 +119,7 @@ export const parseNativeMap = (firestore: Object, nativeData: Object): Object =>
|
|||
return data;
|
||||
};
|
||||
|
||||
const parseNativeArray = (firestore: Object, nativeArray: Object[]): any[] => {
|
||||
const parseNativeArray = (firestore: Firestore, nativeArray: TypeMap[]): any[] => {
|
||||
const array = [];
|
||||
if (nativeArray) {
|
||||
nativeArray.forEach((typeMap) => {
|
||||
|
@ -104,7 +129,7 @@ const parseNativeArray = (firestore: Object, nativeArray: Object[]): any[] => {
|
|||
return array;
|
||||
};
|
||||
|
||||
const parseTypeMap = (firestore: Object, typeMap: TypeMap): any => {
|
||||
const parseTypeMap = (firestore: Firestore, typeMap: TypeMap): any => {
|
||||
const { type, value } = typeMap;
|
||||
if (type === 'null') {
|
||||
return null;
|
||||
|
|
|
@ -6,9 +6,10 @@ import { NativeModules } from 'react-native';
|
|||
import Log from '../utils/log';
|
||||
import INTERNALS from './../internals';
|
||||
import FirebaseCore from './../firebase';
|
||||
import FirebaseApp from '../firebase-app';
|
||||
import { nativeWithApp } from './../utils';
|
||||
|
||||
import type FirebaseApp from '../firebase-app';
|
||||
|
||||
const logs = {};
|
||||
|
||||
// Firebase Native SDKs that support multiple app instances
|
||||
|
@ -50,7 +51,7 @@ export default class ModuleBase {
|
|||
_options: Object;
|
||||
_appName: string;
|
||||
_namespace: string;
|
||||
_firebaseApp: Object;
|
||||
_firebaseApp: FirebaseApp;
|
||||
_eventEmitter: Object;
|
||||
static _NAMESPACE: string;
|
||||
static _NATIVE_MODULE: string;
|
||||
|
@ -61,7 +62,7 @@ export default class ModuleBase {
|
|||
* @param options
|
||||
* @param withEventEmitter
|
||||
*/
|
||||
constructor(firebaseApp: Object, options: Object, withEventEmitter: boolean = false) {
|
||||
constructor(firebaseApp: FirebaseApp, options: Object, withEventEmitter: boolean = false) {
|
||||
this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', '');
|
||||
this._firebaseApp = firebaseApp;
|
||||
this._appName = firebaseApp._name;
|
||||
|
@ -73,12 +74,7 @@ export default class ModuleBase {
|
|||
const nativeModule = NativeModules[this.constructor._NATIVE_MODULE];
|
||||
|
||||
if (!nativeModule) {
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_MISSING_MODULE(
|
||||
this.constructor._NAMESPACE,
|
||||
this.constructor._NATIVE_MODULE,
|
||||
),
|
||||
);
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(this.constructor._NAMESPACE, this.constructor._NATIVE_MODULE));
|
||||
}
|
||||
|
||||
// used by the modules that extend ModuleBase
|
||||
|
@ -100,7 +96,7 @@ export default class ModuleBase {
|
|||
* @param moduleName
|
||||
* @private
|
||||
*/
|
||||
_setupEventEmitter(nativeModule, moduleName) {
|
||||
_setupEventEmitter(nativeModule: Object, moduleName: string) {
|
||||
this._eventEmitter = FirebaseCore._getOrSetNativeEmitter(`${this._appName}-${this._module}`, nativeModule);
|
||||
const events = NATIVE_MODULE_EVENTS[moduleName];
|
||||
|
||||
|
@ -117,7 +113,7 @@ export default class ModuleBase {
|
|||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
_getAppEventName(eventName) {
|
||||
_getAppEventName(eventName: string) {
|
||||
return `${this._appName}-${eventName}`;
|
||||
}
|
||||
|
||||
|
@ -131,9 +127,7 @@ export default class ModuleBase {
|
|||
|
||||
get log(): Log {
|
||||
if (logs[this._namespace]) return logs[this._namespace];
|
||||
return logs[this._namespace] = Log.createLogger(
|
||||
`🔥 ${this._namespace.toUpperCase()}`,
|
||||
);
|
||||
return logs[this._namespace] = Log.createLogger(`🔥 ${this._namespace.toUpperCase()}`);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
/**
|
||||
* @flow
|
||||
*/
|
||||
import Log from './log';
|
||||
|
||||
import type Database from '../modules/database';
|
||||
import type Storage from '../modules/storage';
|
||||
|
||||
export default class ReferenceBase {
|
||||
constructor(path: string, module) {
|
||||
_module: Database | Storage;
|
||||
path: string;
|
||||
|
||||
constructor(path: string, module: Database | Storage) {
|
||||
this._module = module;
|
||||
this.path = path || '/';
|
||||
}
|
||||
|
@ -17,7 +25,7 @@ export default class ReferenceBase {
|
|||
return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
get log() {
|
||||
get log(): Log {
|
||||
return this._module.log;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/**
|
||||
* @flow
|
||||
*/
|
||||
import { NativeEventEmitter } from 'react-native';
|
||||
|
||||
import INTERNALS from './../internals';
|
||||
|
@ -6,13 +9,13 @@ import DatabaseReference from './../modules/database/reference';
|
|||
import { isString, nativeToJSError } from './../utils';
|
||||
|
||||
type Registration = {
|
||||
key: String,
|
||||
path: String,
|
||||
once?: Boolean,
|
||||
appName: String,
|
||||
eventType: String,
|
||||
key: string,
|
||||
path: string,
|
||||
once?: boolean,
|
||||
appName: string,
|
||||
eventType: string,
|
||||
listener: Function,
|
||||
eventRegistrationKey: String,
|
||||
eventRegistrationKey: string,
|
||||
ref: DatabaseReference,
|
||||
}
|
||||
|
||||
|
@ -21,7 +24,12 @@ type Registration = {
|
|||
* subscriptions and keep the listeners in sync in js vs native.
|
||||
*/
|
||||
export default class SyncTree {
|
||||
constructor(databaseNative) {
|
||||
_databaseNative: Object;
|
||||
_nativeEmitter: NativeEventEmitter;
|
||||
_reverseLookup: { [string]: Registration };
|
||||
_tree: { [string]: { [string]: Array }};
|
||||
|
||||
constructor(databaseNative: Object) {
|
||||
this._tree = {};
|
||||
this._reverseLookup = {};
|
||||
this._databaseNative = databaseNative;
|
||||
|
@ -110,7 +118,7 @@ export default class SyncTree {
|
|||
* @param registration
|
||||
* @return {null}
|
||||
*/
|
||||
getRegistration(registration): Registration | null {
|
||||
getRegistration(registration: string): Registration | null {
|
||||
return this._reverseLookup[registration] ? Object.assign({}, this._reverseLookup[registration]) : null;
|
||||
}
|
||||
|
||||
|
@ -120,7 +128,7 @@ export default class SyncTree {
|
|||
* @param registrations
|
||||
* @return {number}
|
||||
*/
|
||||
removeListenersForRegistrations(registrations) {
|
||||
removeListenersForRegistrations(registrations: string | string[]) {
|
||||
if (isString(registrations)) {
|
||||
this.removeRegistration(registrations);
|
||||
INTERNALS.SharedEventEmitter.removeAllListeners(registrations);
|
||||
|
@ -143,7 +151,7 @@ export default class SyncTree {
|
|||
* @param registrations
|
||||
* @return {Array} array of registrations removed
|
||||
*/
|
||||
removeListenerRegistrations(listener, registrations) {
|
||||
removeListenerRegistrations(listener, registrations: string[]) {
|
||||
if (!Array.isArray(registrations)) return [];
|
||||
const removed = [];
|
||||
|
||||
|
@ -173,7 +181,7 @@ export default class SyncTree {
|
|||
* @param path
|
||||
* @return {Array}
|
||||
*/
|
||||
getRegistrationsByPath(path): Array {
|
||||
getRegistrationsByPath(path: string): Array {
|
||||
const out = [];
|
||||
const eventKeys = Object.keys(this._tree[path] || {});
|
||||
|
||||
|
@ -191,7 +199,7 @@ export default class SyncTree {
|
|||
* @param eventType
|
||||
* @return {Array}
|
||||
*/
|
||||
getRegistrationsByPathEvent(path, eventType): Array {
|
||||
getRegistrationsByPathEvent(path: string, eventType: string): Array {
|
||||
if (!this._tree[path]) return [];
|
||||
if (!this._tree[path][eventType]) return [];
|
||||
|
||||
|
@ -228,8 +236,13 @@ export default class SyncTree {
|
|||
* @param listener
|
||||
* @return {String}
|
||||
*/
|
||||
addRegistration(parameters: Registration, listener): String {
|
||||
const { path, eventType, eventRegistrationKey, once } = parameters;
|
||||
addRegistration(parameters: Registration, listener: Function): string {
|
||||
const {
|
||||
path,
|
||||
eventType,
|
||||
eventRegistrationKey,
|
||||
once,
|
||||
} = parameters;
|
||||
|
||||
if (!this._tree[path]) this._tree[path] = {};
|
||||
if (!this._tree[path][eventType]) this._tree[path][eventType] = {};
|
||||
|
@ -256,7 +269,7 @@ export default class SyncTree {
|
|||
* @param registration
|
||||
* @return {boolean}
|
||||
*/
|
||||
removeRegistration(registration: String): Boolean {
|
||||
removeRegistration(registration: string): boolean {
|
||||
if (!this._reverseLookup[registration]) return false;
|
||||
const { path, eventType, once } = this._reverseLookup[registration];
|
||||
|
||||
|
@ -298,4 +311,3 @@ export default class SyncTree {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,18 +6,10 @@ import { Platform } from 'react-native';
|
|||
// modeled after base64 web-safe chars, but ordered by ASCII
|
||||
const PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
|
||||
const AUTO_ID_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
const { hasOwnProperty } = Object;
|
||||
|
||||
// const DEFAULT_CHUNK_SIZE = 50;
|
||||
|
||||
// Source: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical
|
||||
const REGEXP_FIELD_NAME = new RegExp(
|
||||
`^(?:\\.?((?:(?:[A-Za-z_][A-Za-z_0-9]*)|(?:[A-Za-z_][A-Za-z_0-9]*))+))$`
|
||||
);
|
||||
const REGEXP_FIELD_PATH = new RegExp(
|
||||
`^((?:(?:[A-Za-z_][A-Za-z_0-9]*)|(?:[A-Za-z_][A-Za-z_0-9]*))+)(?:\\.((?:(?:[A-Za-z_][A-Za-z_0-9]*)|(?:[A-Za-z_][A-Za-z_0-9]*))+))*$`
|
||||
);
|
||||
|
||||
/**
|
||||
* Deep get a value from an object.
|
||||
* @website https://github.com/Salakar/deeps
|
||||
|
@ -26,9 +18,7 @@ const REGEXP_FIELD_PATH = new RegExp(
|
|||
* @param joiner
|
||||
* @returns {*}
|
||||
*/
|
||||
export function deepGet(object: Object,
|
||||
path: string,
|
||||
joiner?: string = '/'): any {
|
||||
export function deepGet(object: Object, path: string, joiner?: string = '/'): any {
|
||||
const keys = path.split(joiner);
|
||||
|
||||
let i = 0;
|
||||
|
@ -52,9 +42,7 @@ export function deepGet(object: Object,
|
|||
* @param joiner
|
||||
* @returns {*}
|
||||
*/
|
||||
export function deepExists(object: Object,
|
||||
path: string,
|
||||
joiner?: string = '/'): boolean {
|
||||
export function deepExists(object: Object, path: string, joiner?: string = '/'): boolean {
|
||||
const keys = path.split(joiner);
|
||||
|
||||
let i = 0;
|
||||
|
@ -98,7 +86,7 @@ export function areObjectKeysContainedInOther(obj1 : Object, obj2: Object): bool
|
|||
* @param arr2
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isArrayContainedInOther(arr1: Array, arr2: Array): boolean {
|
||||
export function isArrayContainedInOther(arr1: Array<*>, arr2: Array<*>): boolean {
|
||||
if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -112,8 +100,8 @@ export function isArrayContainedInOther(arr1: Array, arr2: Array): boolean {
|
|||
* @param item
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isObject(item: any): boolean {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
|
||||
export function isObject(item: mixed): boolean %checks {
|
||||
return item ? (typeof item === 'object' && !Array.isArray(item) && item !== null) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,8 +109,8 @@ export function isObject(item: any): boolean {
|
|||
* @param item
|
||||
* @returns {*|boolean}
|
||||
*/
|
||||
export function isFunction(item?: any): boolean {
|
||||
return Boolean(item && typeof item === 'function');
|
||||
export function isFunction(item?: mixed): boolean %checks {
|
||||
return item ? typeof item === 'function' : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,20 +118,10 @@ export function isFunction(item?: any): boolean {
|
|||
* @param value
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isString(value: any): boolean {
|
||||
export function isString(value: mixed): boolean %checks {
|
||||
return typeof value === 'string';
|
||||
}
|
||||
|
||||
/**
|
||||
* Firestore field name/path validator.
|
||||
* @param field
|
||||
* @param paths
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isValidFirestoreField(field, paths) {
|
||||
return (paths ? REGEXP_FIELD_PATH : REGEXP_FIELD_NAME).test(field);
|
||||
}
|
||||
|
||||
// platform checks
|
||||
export const isIOS = Platform.OS === 'ios';
|
||||
export const isAndroid = Platform.OS === 'android';
|
||||
|
@ -167,7 +145,7 @@ export function tryJSONParse(string: string | null): any {
|
|||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export function tryJSONStringify(data: any): string | null {
|
||||
export function tryJSONStringify(data: mixed): string | null {
|
||||
try {
|
||||
return JSON.stringify(data);
|
||||
} catch (jsonError) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
|
@ -75,13 +75,13 @@
|
|||
"babel-preset-react-native": "^1.9.0",
|
||||
"debug": "^2.2.0",
|
||||
"enzyme": "^2.4.1",
|
||||
"eslint": "^3.8.1",
|
||||
"eslint-config-airbnb": "^12.0.0",
|
||||
"eslint-plugin-flowtype": "^2.20.0",
|
||||
"eslint-plugin-import": "^2.0.1",
|
||||
"eslint-plugin-jsx-a11y": "^2.2.3",
|
||||
"eslint-plugin-react": "^6.4.1",
|
||||
"flow-bin": "^0.55.0",
|
||||
"eslint": "^4.11.0",
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-plugin-flowtype": "^2.39.1",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"flow-bin": "^0.56.0",
|
||||
"react": "^16.0.0",
|
||||
"react-dom": "^16.0.0",
|
||||
"react-native": "^0.48.0",
|
||||
|
|
|
@ -208,7 +208,7 @@ SPEC CHECKSUMS:
|
|||
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
|
||||
Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8
|
||||
React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee
|
||||
RNFirebase: a76befd482c5e84df7f69893358abda498ee9f76
|
||||
RNFirebase: 1b8adf4dfe740fbc4a69a147715c2edfd041eb92
|
||||
yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a
|
||||
|
||||
PODFILE CHECKSUM: b5674be55653f5dda937c8b794d0479900643d45
|
||||
|
|
|
@ -1033,7 +1033,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6AE1012F46FF8A4D1D818A12 /* [CP] Copy Pods Resources */ = {
|
||||
|
|
Loading…
Reference in New Issue