@@ -22,15 +22,22 @@ import { FirebaseApp, _FirebaseService } from '@firebase/app-types-exp';
22
22
import { Provider } from '@firebase/component' ;
23
23
24
24
import { FirebaseAuthInternalName } from '@firebase/auth-interop-types' ;
25
- import { FirestoreClient } from '../../../src/core/firestore_client' ;
25
+ import {
26
+ FirestoreClient ,
27
+ PersistenceSettings
28
+ } from '../../../src/core/firestore_client' ;
26
29
import { AsyncQueue } from '../../../src/util/async_queue' ;
27
30
import {
28
31
ComponentProvider ,
32
+ IndexedDbComponentProvider ,
29
33
MemoryComponentProvider
30
34
} from '../../../src/core/component_provider' ;
31
35
32
36
import { Firestore as LiteFirestore } from '../../../lite/src/api/database' ;
33
37
import { cast } from '../../../lite/src/api/util' ;
38
+ import { Code , FirestoreError } from '../../../src/util/error' ;
39
+ import { Deferred } from '../../../src/util/promise' ;
40
+ import { LruParams } from '../../../src/local/lru_garbage_collector' ;
34
41
35
42
/**
36
43
* The root reference to the Firestore database and the entry point for the
@@ -45,10 +52,13 @@ export class Firestore extends LiteFirestore
45
52
// Assigned via _getFirestoreClient()
46
53
private _firestoreClientPromise ?: Promise < FirestoreClient > ;
47
54
55
+ protected _persistenceSettings : PersistenceSettings = { durable : false } ;
48
56
// We override the Settings property of the Lite SDK since the full Firestore
49
57
// SDK supports more settings.
50
58
protected _settings ?: firestore . Settings ;
51
59
60
+ _terminated : boolean = false ;
61
+
52
62
constructor (
53
63
app : FirebaseApp ,
54
64
authProvider : Provider < FirebaseAuthInternalName >
@@ -80,16 +90,72 @@ export class Firestore extends LiteFirestore
80
90
) ;
81
91
82
92
this . _firestoreClientPromise = firestoreClient
83
- . start ( this . _componentProvider , { durable : false } )
93
+ . start ( this . _componentProvider , this . _persistenceSettings )
84
94
. then ( ( ) => firestoreClient ) ;
85
95
}
86
96
87
97
return this . _firestoreClientPromise ;
88
98
}
89
99
100
+ // TODO(firestorexp): Factor out MultiTabComponentProvider and remove
101
+ // `synchronizeTabs` argument
102
+ _enablePersistence (
103
+ persistenceProvider : ComponentProvider ,
104
+ synchronizeTabs : boolean
105
+ ) : Promise < void > {
106
+ if ( this . _firestoreClientPromise ) {
107
+ throw new FirestoreError (
108
+ Code . FAILED_PRECONDITION ,
109
+ 'Firestore has already been started and persistence can no longer ' +
110
+ 'be enabled. You can only call enable persistence before calling ' +
111
+ 'any other methods on a Firestore object.'
112
+ ) ;
113
+ }
114
+
115
+ const settings = this . _getSettings ( ) ;
116
+ this . _persistenceSettings = {
117
+ durable : true ,
118
+ synchronizeTabs,
119
+ forceOwningTab : false ,
120
+ cacheSizeBytes :
121
+ settings . cacheSizeBytes ?? LruParams . DEFAULT_CACHE_SIZE_BYTES
122
+ } ;
123
+ this . _componentProvider = persistenceProvider ;
124
+
125
+ // TODO(firestorexp): Add support for Persistence fallback
126
+ return this . _getFirestoreClient ( ) . then ( ( ) => { } ) ;
127
+ }
128
+
90
129
delete ( ) : Promise < void > {
91
130
return terminate ( this ) ;
92
131
}
132
+
133
+ _clearPersistence ( ) : Promise < void > {
134
+ if ( this . _firestoreClientPromise !== undefined && ! this . _terminated ) {
135
+ throw new FirestoreError (
136
+ Code . FAILED_PRECONDITION ,
137
+ 'Persistence can only be cleared before the Firestore instance is ' +
138
+ 'initialized or after it is terminated.'
139
+ ) ;
140
+ }
141
+
142
+ const settings = this . _getSettings ( ) ;
143
+ const deferred = new Deferred < void > ( ) ;
144
+ this . _queue . enqueueAndForgetEvenAfterShutdown ( async ( ) => {
145
+ try {
146
+ const databaseInfo = this . _makeDatabaseInfo (
147
+ settings . host ,
148
+ settings . ssl ,
149
+ settings . experimentalForceLongPolling
150
+ ) ;
151
+ await this . _componentProvider . clearPersistence ( databaseInfo ) ;
152
+ deferred . resolve ( ) ;
153
+ } catch ( e ) {
154
+ deferred . reject ( e ) ;
155
+ }
156
+ } ) ;
157
+ return deferred . promise ;
158
+ }
93
159
}
94
160
95
161
export function initializeFirestore (
@@ -108,11 +174,66 @@ export function getFirestore(app: FirebaseApp): Firestore {
108
174
return _getProvider ( app , 'firestore-exp' ) . getImmediate ( ) as Firestore ;
109
175
}
110
176
177
+ export function enableIndexedDbPersistence (
178
+ firestore : firestore . FirebaseFirestore
179
+ ) : Promise < void > {
180
+ const firestoreImpl = cast ( firestore , Firestore ) ;
181
+ return firestoreImpl . _enablePersistence (
182
+ new IndexedDbComponentProvider ( ) ,
183
+ /*synchronizeTabs=*/ false
184
+ ) ;
185
+ }
186
+
187
+ export function enableMultiTabIndexedDbPersistence (
188
+ firestore : firestore . FirebaseFirestore
189
+ ) : Promise < void > {
190
+ const firestoreImpl = cast ( firestore , Firestore ) ;
191
+ return firestoreImpl . _enablePersistence (
192
+ new IndexedDbComponentProvider ( ) ,
193
+ /*synchronizeTabs=*/ true
194
+ ) ;
195
+ }
196
+
197
+ export function clearIndexedDbPersistence (
198
+ firestore : firestore . FirebaseFirestore
199
+ ) : Promise < void > {
200
+ const firestoreImpl = cast ( firestore , Firestore ) ;
201
+ return firestoreImpl . _clearPersistence ( ) ;
202
+ }
203
+
204
+ export function waitForPendingWrites (
205
+ firestore : firestore . FirebaseFirestore
206
+ ) : Promise < void > {
207
+ const firestoreImpl = cast ( firestore , Firestore ) ;
208
+ return firestoreImpl
209
+ . _getFirestoreClient ( )
210
+ . then ( firestoreClient => firestoreClient . waitForPendingWrites ( ) ) ;
211
+ }
212
+
213
+ export function enableNetwork (
214
+ firestore : firestore . FirebaseFirestore
215
+ ) : Promise < void > {
216
+ const firestoreImpl = cast ( firestore , Firestore ) ;
217
+ return firestoreImpl
218
+ . _getFirestoreClient ( )
219
+ . then ( firestoreClient => firestoreClient . enableNetwork ( ) ) ;
220
+ }
221
+
222
+ export function disableNetwork (
223
+ firestore : firestore . FirebaseFirestore
224
+ ) : Promise < void > {
225
+ const firestoreImpl = cast ( firestore , Firestore ) ;
226
+ return firestoreImpl
227
+ . _getFirestoreClient ( )
228
+ . then ( firestoreClient => firestoreClient . disableNetwork ( ) ) ;
229
+ }
230
+
111
231
export function terminate (
112
232
firestore : firestore . FirebaseFirestore
113
233
) : Promise < void > {
114
234
_removeServiceInstance ( firestore . app , 'firestore/lite' ) ;
115
235
const firestoreImpl = cast ( firestore , Firestore ) ;
236
+ firestoreImpl . _terminated = true ;
116
237
return firestoreImpl
117
238
. _getFirestoreClient ( )
118
239
. then ( firestoreClient => firestoreClient . terminate ( ) ) ;
0 commit comments