@@ -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,71 @@ 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 ( ) {
134
+ if ( this . _firestoreClientPromise !== undefined && ! this . _terminated ) {
135
+ throw new FirestoreError (
136
+ Code . FAILED_PRECONDITION ,
137
+ 'Persistence cannot be cleared after this Firestore instance is initialized.'
138
+ ) ;
139
+ }
140
+
141
+ const settings = this . _getSettings ( ) ;
142
+ const deferred = new Deferred < void > ( ) ;
143
+ this . _queue . enqueueAndForgetEvenAfterShutdown ( async ( ) => {
144
+ try {
145
+ const databaseInfo = this . _makeDatabaseInfo (
146
+ settings . host ,
147
+ settings . ssl ,
148
+ settings . experimentalForceLongPolling
149
+ ) ;
150
+ await this . _componentProvider . clearPersistence ( databaseInfo ) ;
151
+ deferred . resolve ( ) ;
152
+ } catch ( e ) {
153
+ deferred . reject ( e ) ;
154
+ }
155
+ } ) ;
156
+ return deferred . promise ;
157
+ }
93
158
}
94
159
95
160
export function initializeFirestore (
@@ -108,11 +173,66 @@ export function getFirestore(app: FirebaseApp): Firestore {
108
173
return _getProvider ( app , 'firestore-exp' ) . getImmediate ( ) as Firestore ;
109
174
}
110
175
176
+ export function enableIndexedDbPersistence (
177
+ firestore : firestore . FirebaseFirestore
178
+ ) : Promise < void > {
179
+ const firestoreImpl = cast ( firestore , Firestore ) ;
180
+ return firestoreImpl . _enablePersistence (
181
+ new IndexedDbComponentProvider ( ) ,
182
+ /*synchronizeTabs=*/ false
183
+ ) ;
184
+ }
185
+
186
+ export function enableMultiTabIndexedDbPersistence (
187
+ firestore : firestore . FirebaseFirestore
188
+ ) : Promise < void > {
189
+ const firestoreImpl = cast ( firestore , Firestore ) ;
190
+ return firestoreImpl . _enablePersistence (
191
+ new IndexedDbComponentProvider ( ) ,
192
+ /*synchronizeTabs=*/ true
193
+ ) ;
194
+ }
195
+
196
+ export function clearIndexedDbPersistence (
197
+ firestore : firestore . FirebaseFirestore
198
+ ) : Promise < void > {
199
+ const firestoreImpl = cast ( firestore , Firestore ) ;
200
+ return firestoreImpl . _clearPersistence ( ) ;
201
+ }
202
+
203
+ export function waitForPendingWrites (
204
+ firestore : firestore . FirebaseFirestore
205
+ ) : Promise < void > {
206
+ const firestoreImpl = cast ( firestore , Firestore ) ;
207
+ return firestoreImpl
208
+ . _getFirestoreClient ( )
209
+ . then ( firestoreClient => firestoreClient . waitForPendingWrites ( ) ) ;
210
+ }
211
+
212
+ export function enableNetwork (
213
+ firestore : firestore . FirebaseFirestore
214
+ ) : Promise < void > {
215
+ const firestoreImpl = cast ( firestore , Firestore ) ;
216
+ return firestoreImpl
217
+ . _getFirestoreClient ( )
218
+ . then ( firestoreClient => firestoreClient . enableNetwork ( ) ) ;
219
+ }
220
+
221
+ export function disableNetwork (
222
+ firestore : firestore . FirebaseFirestore
223
+ ) : Promise < void > {
224
+ const firestoreImpl = cast ( firestore , Firestore ) ;
225
+ return firestoreImpl
226
+ . _getFirestoreClient ( )
227
+ . then ( firestoreClient => firestoreClient . disableNetwork ( ) ) ;
228
+ }
229
+
111
230
export function terminate (
112
231
firestore : firestore . FirebaseFirestore
113
232
) : Promise < void > {
114
233
_removeServiceInstance ( firestore . app , 'firestore/lite' ) ;
115
234
const firestoreImpl = cast ( firestore , Firestore ) ;
235
+ firestoreImpl . _terminated = true ;
116
236
return firestoreImpl
117
237
. _getFirestoreClient ( )
118
238
. then ( firestoreClient => firestoreClient . terminate ( ) ) ;
0 commit comments