22 * @flow
33 * Database representation wrapper
44 */
5- 'use strict' ;
65import { NativeModules , NativeEventEmitter } from 'react-native' ;
7- const FirestackDatabase = NativeModules . FirestackDatabase ;
8- const FirestackDatabaseEvt = new NativeEventEmitter ( FirestackDatabase ) ;
9-
10- import { promisify } from './../../utils' ;
11-
126import { Base } from './../base' ;
13- import Reference from './reference.js' ;
147import Snapshot from './snapshot.js' ;
8+ import Reference from './reference.js' ;
9+ import { promisify , isFunction } from './../../utils' ;
10+
11+ const FirestackDatabase = NativeModules . FirestackDatabase ;
12+ const FirestackDatabaseEvt = new NativeEventEmitter ( FirestackDatabase ) ;
1513
1614/**
1715 * @class Database
1816 */
1917export default class Database extends Base {
2018 constructor ( firestack : Object , options : Object = { } ) {
2119 super ( firestack , options ) ;
22- this . log . debug ( 'Created new Database instance' , this . options ) ;
23-
20+ this . subscriptions = { } ;
2421 this . persistenceEnabled = false ;
25- this . successListener = FirestackDatabaseEvt
26- . addListener (
27- 'database_event' ,
28- event => this . handleDatabaseEvent ( event ) ) ;
29- this . errorListener = FirestackDatabaseEvt
30- . addListener (
31- 'database_error' ,
32- err => this . handleDatabaseError ( err ) ) ;
33-
34- this . dbSubscriptions = { } ;
22+ this . namespace = 'firestack:database' ;
23+
24+ this . successListener = FirestackDatabaseEvt . addListener (
25+ 'database_event' ,
26+ event => this . _handleDatabaseEvent ( event )
27+ ) ;
28+
29+ this . errorListener = FirestackDatabaseEvt . addListener (
30+ 'database_error' ,
31+ err => this . _handleDatabaseError ( err )
32+ ) ;
33+
34+ this . log . debug ( 'Created new Database instance' , this . options ) ;
3535 }
3636
37+ /**
38+ * Returns a new firestack reference instance
39+ * @param path
40+ * @returns {Reference }
41+ */
3742 ref ( ...path : Array < string > ) {
3843 return new Reference ( this , path ) ;
3944 }
4045
46+ /**
47+ * Enabled / disable database persistence
48+ * @param enable
49+ * @returns {* }
50+ */
4151 setPersistence ( enable : boolean = true ) {
42- let promise ;
4352 if ( this . persistenceEnabled !== enable ) {
4453 this . log . debug ( `${ enable ? 'Enabling' : 'Disabling' } persistence` ) ;
45- promise = this . whenReady ( promisify ( 'enablePersistence' , FirestackDatabase ) ( enable ) ) ;
4654 this . persistenceEnabled = enable ;
47- } else {
48- promise = this . whenReady ( Promise . resolve ( { status : 'Already enabled' } ) )
49- }
50-
51- return promise ;
52- }
53-
54- handleDatabaseEvent ( event : Object ) {
55- const body = event . body || { } ;
56- const { path, modifiersString, eventName, snapshot } = body ;
57- const dbHandle = this . _dbHandle ( path , modifiersString ) ;
58- this . log . debug ( 'handleDatabaseEvent: ' , dbHandle , eventName , snapshot && snapshot . key ) ;
59-
60- if ( this . dbSubscriptions [ dbHandle ] && this . dbSubscriptions [ dbHandle ] [ eventName ] ) {
61- this . dbSubscriptions [ dbHandle ] [ eventName ] . forEach ( cb => {
62- if ( cb && typeof ( cb ) === 'function' ) {
63- const snap = new Snapshot ( this , snapshot ) ;
64- cb ( snap , body ) ;
65- }
66- } )
67- } else {
68- FirestackDatabase . off ( path , modifiersString , eventName , ( ) => {
69- this . log . debug ( 'handleDatabaseEvent: No JS listener registered, removed native listener' , dbHandle , eventName ) ;
70- } ) ;
55+ return this . whenReady ( promisify ( 'enablePersistence' , FirestackDatabase ) ( enable ) ) ;
7156 }
72- }
7357
74- handleDatabaseError ( err : Object ) {
75- this . log . debug ( 'handleDatabaseError ->' , err ) ;
58+ return this . whenReady ( Promise . resolve ( { status : 'Already enabled' } ) ) ;
7659 }
7760
61+ /**
62+ *
63+ * @param path
64+ * @param modifiersString
65+ * @param modifiers
66+ * @param eventName
67+ * @param cb
68+ * @returns {* }
69+ */
7870 on ( path : string , modifiersString : string , modifiers : Array < string > , eventName : string , cb : ( ) = > void ) {
79- const dbHandle = this . _dbHandle ( path , modifiersString ) ;
80- this . log . debug ( 'adding on listener' , dbHandle ) ;
81-
82- if ( this . dbSubscriptions [ dbHandle ] ) {
83- if ( this . dbSubscriptions [ dbHandle ] [ eventName ] ) {
84- this . dbSubscriptions [ dbHandle ] [ eventName ] . push ( cb ) ;
85- } else {
86- this . dbSubscriptions [ dbHandle ] [ eventName ] = [ cb ] ;
87- }
71+ const handle = this . _handle ( path , modifiersString ) ;
72+ this . log . debug ( 'adding on listener' , handle ) ;
73+
74+ if ( this . subscriptions [ handle ] ) {
75+ if ( this . subscriptions [ handle ] [ eventName ] ) this . subscriptions [ handle ] [ eventName ] . push ( cb ) ;
76+ else this . subscriptions [ handle ] [ eventName ] = [ cb ] ;
8877 } else {
89- this . dbSubscriptions [ dbHandle ] = {
90- [ eventName ] : [ cb ]
91- }
78+ this . subscriptions [ handle ] = { [ eventName ] : [ cb ] } ;
9279 }
9380
9481 return promisify ( 'on' , FirestackDatabase ) ( path , modifiersString , modifiers , eventName ) ;
9582 }
9683
84+ /**
85+ *
86+ * @param path
87+ * @param modifiersString
88+ * @param eventName
89+ * @param origCB
90+ * @returns {* }
91+ */
9792 off ( path : string , modifiersString : string , eventName ?: string , origCB ?: ( ) => void ) {
98- const dbHandle = this . _dbHandle ( path , modifiersString ) ;
99- this . log . debug ( 'off() : ' , dbHandle , eventName ) ;
93+ const handle = this . _handle ( path , modifiersString ) ;
94+ this . log . debug ( 'off() : ' , handle , eventName ) ;
10095
101- if ( ! this . dbSubscriptions [ dbHandle ]
102- || ( eventName && ! this . dbSubscriptions [ dbHandle ] [ eventName ] ) ) {
103- this . log . warn ( 'off() called, but not currently listening at that location (bad path)' , dbHandle , eventName ) ;
96+ if ( ! this . subscriptions [ handle ] || ( eventName && ! this . subscriptions [ handle ] [ eventName ] ) ) {
97+ this . log . warn ( 'off() called, but not currently listening at that location (bad path)' , handle , eventName ) ;
10498 return Promise . resolve ( ) ;
10599 }
106100
107101 if ( eventName && origCB ) {
108- const i = this . dbSubscriptions [ dbHandle ] [ eventName ] . indexOf ( origCB ) ;
102+ const i = this . subscriptions [ handle ] [ eventName ] . indexOf ( origCB ) ;
109103 if ( i === - 1 ) {
110- this . log . warn ( 'off() called, but the callback specifed is not listening at that location (bad path)' , dbHandle , eventName ) ;
104+ this . log . warn ( 'off() called, but the callback specifed is not listening at that location (bad path)' , handle , eventName ) ;
105+ return Promise . resolve ( ) ;
106+ }
107+
108+ this . subscriptions [ handle ] [ eventName ] = this . subscriptions [ handle ] [ eventName ] . splice ( i , 1 ) ;
109+
110+ if ( this . subscriptions [ handle ] [ eventName ] . length > 0 ) {
111111 return Promise . resolve ( ) ;
112- } else {
113- this . dbSubscriptions [ dbHandle ] [ eventName ] = this . dbSubscriptions [ dbHandle ] [ eventName ] . splice ( i , 1 ) ;
114- if ( this . dbSubscriptions [ dbHandle ] [ eventName ] . length > 0 ) {
115- return Promise . resolve ( ) ;
116- }
117112 }
118113 } else if ( eventName ) {
119- this . dbSubscriptions [ dbHandle ] [ eventName ] = [ ] ;
114+ this . subscriptions [ handle ] [ eventName ] = [ ] ;
120115 } else {
121- this . dbSubscriptions [ dbHandle ] = { }
116+ this . subscriptions [ handle ] = { } ;
122117 }
118+
123119 return promisify ( 'off' , FirestackDatabase ) ( path , modifiersString , eventName ) ;
124120 }
125121
122+ /**
123+ * Removes all event handlers and their native subscriptions
124+ * @returns {Promise.<*> }
125+ */
126126 cleanup ( ) {
127- let promises = [ ] ;
128- Object . keys ( this . dbSubscriptions ) . forEach ( dbHandle => {
129- Object . keys ( this . dbSubscriptions [ dbHandle ] ) . forEach ( eventName => {
130- let separator = dbHandle . indexOf ( '|' ) ;
131- let path = dbHandle . substring ( 0 , separator ) ;
132- let modifiersString = dbHandle . substring ( separator + 1 ) ;
133-
134- promises . push ( this . off ( path , modifiersString , eventName ) )
135- } )
136- } )
137- return Promise . all ( promises ) ;
138- }
127+ const promises = [ ] ;
128+ Object . keys ( this . subscriptions ) . forEach ( ( handle ) => {
129+ Object . keys ( this . subscriptions [ handle ] ) . forEach ( ( eventName ) => {
130+ const separator = handle . indexOf ( '|' ) ;
131+ const path = handle . substring ( 0 , separator ) ;
132+ const modifiersString = handle . substring ( separator + 1 ) ;
133+ promises . push ( this . off ( path , modifiersString , eventName ) ) ;
134+ } ) ;
135+ } ) ;
139136
140- _dbHandle ( path : string = '' , modifiersString : string = '' ) {
141- return path + '|' + modifiersString ;
137+ return Promise . all ( promises ) ;
142138 }
143139
144140 goOnline ( ) {
@@ -149,7 +145,52 @@ export default class Database extends Base {
149145 FirestackDatabase . goOffline ( ) ;
150146 }
151147
152- get namespace ( ) : string {
153- return 'firestack :database ';
148+ /**
149+ * INTERNALS
150+ */
151+
152+
153+ /**
154+ *
155+ * @param path
156+ * @param modifiersString
157+ * @returns {string }
158+ * @private
159+ */
160+ _dbHandle ( path : string = '' , modifiersString : string = '' ) {
161+ return `${ path } |${ modifiersString } ` ;
162+ }
163+
164+
165+ /**
166+ *
167+ * @param event
168+ * @private
169+ */
170+ _handleDatabaseEvent ( event : Object ) {
171+ const body = event . body || { } ;
172+ const { path, modifiersString, eventName, snapshot } = body ;
173+ const handle = this . _handle ( path , modifiersString ) ;
174+
175+ this . log . debug ( '_handleDatabaseEvent: ' , handle , eventName , snapshot && snapshot . key ) ;
176+
177+ if ( this . subscriptions [ handle ] && this . subscriptions [ handle ] [ eventName ] ) {
178+ this . subscriptions [ handle ] [ eventName ] . forEach ( ( cb ) => {
179+ if ( isFunction ( cb ) ) cb ( new Snapshot ( this , snapshot ) , body ) ;
180+ } ) ;
181+ } else {
182+ FirestackDatabase . off ( path , modifiersString , eventName , ( ) => {
183+ this . log . debug ( '_handleDatabaseEvent: No JS listener registered, removed native listener' , handle , eventName ) ;
184+ } ) ;
185+ }
186+ }
187+
188+ /**
189+ *
190+ * @param err
191+ * @private
192+ */
193+ _handleDatabaseError ( err : Object ) {
194+ this . log . debug ( '_handleDatabaseError ->' , err ) ;
154195 }
155196}
0 commit comments