Skip to content

Commit ea2094e

Browse files
Add remaining firestore-exp functionality
1 parent fa10434 commit ea2094e

File tree

6 files changed

+16200
-17
lines changed

6 files changed

+16200
-17
lines changed

packages/firestore/exp/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export function waitForPendingWrites(
9191
export function enableNetwork(firestore: FirebaseFirestore): Promise<void>;
9292
export function disableNetwork(firestore: FirebaseFirestore): Promise<void>;
9393

94+
// TODO(firestoreexp): Add experimentalForceOwningTab support
9495
export function enableIndexedDbPersistence(
9596
firestore: FirebaseFirestore
9697
): Promise<void>;

packages/firestore/exp/index.node.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,22 @@ import { Firestore } from './src/api/database';
2323
export { FieldPath, documentId } from '../lite/src/api/field_path';
2424

2525
export {
26-
Firestore,
26+
Firestore as FirebaseFirestore,
2727
initializeFirestore,
2828
getFirestore,
29+
enableIndexedDbPersistence,
30+
enableMultiTabIndexedDbPersistence,
31+
clearIndexedDbPersistence,
32+
waitForPendingWrites,
33+
disableNetwork,
34+
enableNetwork,
2935
terminate
3036
} from './src/api/database';
3137

3238
export {
3339
DocumentSnapshot,
3440
QueryDocumentSnapshot,
41+
QuerySnapshot,
3542
snapshotEqual
3643
} from './src/api/snapshot';
3744

@@ -53,6 +60,9 @@ export {
5360
getDoc,
5461
getDocFromCache,
5562
getDocFromServer,
63+
getQuery,
64+
getQueryFromCache,
65+
getQueryFromServer,
5666
onSnapshot,
5767
onSnapshotsInSync,
5868
setDoc,

packages/firestore/exp/src/api/database.ts

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,22 @@ import { FirebaseApp, _FirebaseService } from '@firebase/app-types-exp';
2222
import { Provider } from '@firebase/component';
2323

2424
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';
2629
import { AsyncQueue } from '../../../src/util/async_queue';
2730
import {
2831
ComponentProvider,
32+
IndexedDbComponentProvider,
2933
MemoryComponentProvider
3034
} from '../../../src/core/component_provider';
3135

3236
import { Firestore as LiteFirestore } from '../../../lite/src/api/database';
3337
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';
3441

3542
/**
3643
* The root reference to the Firestore database and the entry point for the
@@ -45,10 +52,13 @@ export class Firestore extends LiteFirestore
4552
// Assigned via _getFirestoreClient()
4653
private _firestoreClientPromise?: Promise<FirestoreClient>;
4754

55+
protected _persistenceSettings: PersistenceSettings = { durable: false };
4856
// We override the Settings property of the Lite SDK since the full Firestore
4957
// SDK supports more settings.
5058
protected _settings?: firestore.Settings;
5159

60+
_terminated: boolean = false;
61+
5262
constructor(
5363
app: FirebaseApp,
5464
authProvider: Provider<FirebaseAuthInternalName>
@@ -80,16 +90,71 @@ export class Firestore extends LiteFirestore
8090
);
8191

8292
this._firestoreClientPromise = firestoreClient
83-
.start(this._componentProvider, { durable: false })
93+
.start(this._componentProvider, this._persistenceSettings)
8494
.then(() => firestoreClient);
8595
}
8696

8797
return this._firestoreClientPromise;
8898
}
8999

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+
90129
delete(): Promise<void> {
91130
return terminate(this);
92131
}
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+
}
93158
}
94159

95160
export function initializeFirestore(
@@ -108,11 +173,66 @@ export function getFirestore(app: FirebaseApp): Firestore {
108173
return _getProvider(app, 'firestore-exp').getImmediate() as Firestore;
109174
}
110175

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+
111230
export function terminate(
112231
firestore: firestore.FirebaseFirestore
113232
): Promise<void> {
114233
_removeServiceInstance(firestore.app, 'firestore/lite');
115234
const firestoreImpl = cast(firestore, Firestore);
235+
firestoreImpl._terminated = true;
116236
return firestoreImpl
117237
._getFirestoreClient()
118238
.then(firestoreClient => firestoreClient.terminate());

0 commit comments

Comments
 (0)