Skip to content

Commit f8d1b3d

Browse files
Misc fixes for tree-shakeable API (#3358)
1 parent bb74083 commit f8d1b3d

File tree

11 files changed

+94
-45
lines changed

11 files changed

+94
-45
lines changed

.changeset/strong-geckos-peel.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

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

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,18 @@ import {
3333
MemoryComponentProvider
3434
} from '../../../src/core/component_provider';
3535

36-
import { Firestore as LiteFirestore } from '../../../lite/src/api/database';
36+
import {
37+
DEFAULT_FORCE_LONG_POLLING,
38+
DEFAULT_HOST,
39+
DEFAULT_SSL,
40+
Firestore as LiteFirestore
41+
} from '../../../lite/src/api/database';
3742
import { cast } from '../../../lite/src/api/util';
3843
import { Code, FirestoreError } from '../../../src/util/error';
3944
import { Deferred } from '../../../src/util/promise';
4045
import { LruParams } from '../../../src/local/lru_garbage_collector';
46+
import { CACHE_SIZE_UNLIMITED } from '../../../src/api/database';
47+
import { DatabaseInfo } from '../../../src/core/database_info';
4148

4249
/**
4350
* The root reference to the Firestore database and the entry point for the
@@ -46,25 +53,27 @@ import { LruParams } from '../../../src/local/lru_garbage_collector';
4653
export class Firestore extends LiteFirestore
4754
implements firestore.FirebaseFirestore, _FirebaseService {
4855
private readonly _queue = new AsyncQueue();
56+
private readonly _firestoreClient: FirestoreClient;
4957
private readonly _persistenceKey: string;
5058
private _componentProvider: ComponentProvider = new MemoryComponentProvider();
5159

5260
// Assigned via _getFirestoreClient()
53-
private _firestoreClientPromise?: Promise<FirestoreClient>;
61+
private _deferredInitialization?: Promise<void>;
5462

5563
protected _persistenceSettings: PersistenceSettings = { durable: false };
5664
// We override the Settings property of the Lite SDK since the full Firestore
5765
// SDK supports more settings.
5866
protected _settings?: firestore.Settings;
5967

60-
_terminated: boolean = false;
68+
private _terminated: boolean = false;
6169

6270
constructor(
6371
app: FirebaseApp,
6472
authProvider: Provider<FirebaseAuthInternalName>
6573
) {
6674
super(app, authProvider);
6775
this._persistenceKey = app.name;
76+
this._firestoreClient = new FirestoreClient(this._credentials, this._queue);
6877
}
6978

7079
_getSettings(): firestore.Settings {
@@ -75,26 +84,29 @@ export class Firestore extends LiteFirestore
7584
}
7685

7786
_getFirestoreClient(): Promise<FirestoreClient> {
78-
if (!this._firestoreClientPromise) {
87+
if (this._terminated) {
88+
throw new FirestoreError(
89+
Code.FAILED_PRECONDITION,
90+
'The client has already been terminated.'
91+
);
92+
}
93+
94+
if (!this._deferredInitialization) {
7995
const settings = this._getSettings();
8096
const databaseInfo = this._makeDatabaseInfo(
8197
settings.host,
8298
settings.ssl,
8399
settings.experimentalForceLongPolling
84100
);
85101

86-
const firestoreClient = new FirestoreClient(
102+
this._deferredInitialization = this._firestoreClient.start(
87103
databaseInfo,
88-
this._credentials,
89-
this._queue
104+
this._componentProvider,
105+
this._persistenceSettings
90106
);
91-
92-
this._firestoreClientPromise = firestoreClient
93-
.start(this._componentProvider, this._persistenceSettings)
94-
.then(() => firestoreClient);
95107
}
96108

97-
return this._firestoreClientPromise;
109+
return this._deferredInitialization.then(() => this._firestoreClient);
98110
}
99111

100112
// TODO(firestorexp): Factor out MultiTabComponentProvider and remove
@@ -103,11 +115,11 @@ export class Firestore extends LiteFirestore
103115
persistenceProvider: ComponentProvider,
104116
synchronizeTabs: boolean
105117
): Promise<void> {
106-
if (this._firestoreClientPromise) {
118+
if (this._deferredInitialization) {
107119
throw new FirestoreError(
108120
Code.FAILED_PRECONDITION,
109121
'Firestore has already been started and persistence can no longer ' +
110-
'be enabled. You can only call enable persistence before calling ' +
122+
'be enabled. You can only enable persistence before calling ' +
111123
'any other methods on a Firestore object.'
112124
);
113125
}
@@ -131,10 +143,10 @@ export class Firestore extends LiteFirestore
131143
}
132144

133145
_clearPersistence(): Promise<void> {
134-
if (this._firestoreClientPromise !== undefined && !this._terminated) {
146+
if (this._deferredInitialization !== undefined && !this._terminated) {
135147
throw new FirestoreError(
136148
Code.FAILED_PRECONDITION,
137-
'Persistence can only be cleared before the Firestore instance is ' +
149+
'Persistence can only be cleared before a Firestore instance is ' +
138150
'initialized or after it is terminated.'
139151
);
140152
}
@@ -156,6 +168,30 @@ export class Firestore extends LiteFirestore
156168
});
157169
return deferred.promise;
158170
}
171+
172+
protected _makeDatabaseInfo(
173+
host?: string,
174+
ssl?: boolean,
175+
forceLongPolling?: boolean
176+
): DatabaseInfo {
177+
return new DatabaseInfo(
178+
this._databaseId,
179+
this._persistenceKey,
180+
host ?? DEFAULT_HOST,
181+
ssl ?? DEFAULT_SSL,
182+
forceLongPolling ?? DEFAULT_FORCE_LONG_POLLING
183+
);
184+
}
185+
186+
_terminate(): Promise<void> {
187+
this._terminated = true;
188+
if (this._deferredInitialization) {
189+
return this._deferredInitialization.then(() =>
190+
this._firestoreClient.terminate()
191+
);
192+
}
193+
return Promise.resolve();
194+
}
159195
}
160196

161197
export function initializeFirestore(
@@ -166,6 +202,18 @@ export function initializeFirestore(
166202
app,
167203
'firestore-exp'
168204
).getImmediate() as Firestore;
205+
206+
if (
207+
settings.cacheSizeBytes !== undefined &&
208+
settings.cacheSizeBytes !== CACHE_SIZE_UNLIMITED &&
209+
settings.cacheSizeBytes < LruParams.MINIMUM_CACHE_SIZE_BYTES
210+
) {
211+
throw new FirestoreError(
212+
Code.INVALID_ARGUMENT,
213+
`cacheSizeBytes must be at least ${LruParams.MINIMUM_CACHE_SIZE_BYTES}`
214+
);
215+
}
216+
169217
firestore._configureClient(settings);
170218
return firestore;
171219
}
@@ -233,8 +281,5 @@ export function terminate(
233281
): Promise<void> {
234282
_removeServiceInstance(firestore.app, 'firestore/lite');
235283
const firestoreImpl = cast(firestore, Firestore);
236-
firestoreImpl._terminated = true;
237-
return firestoreImpl
238-
._getFirestoreClient()
239-
.then(firestoreClient => firestoreClient.terminate());
284+
return firestoreImpl._terminate();
240285
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import {
5050
} from '../../../lite/src/api/reference';
5151
import { Document } from '../../../src/model/document';
5252
import { DeleteMutation, Precondition } from '../../../src/model/mutation';
53-
import { FieldPath } from '../../../src/api/field_path';
53+
import { FieldPath } from '../../../lite/src/api/field_path';
5454
import {
5555
CompleteFn,
5656
ErrorFn,
@@ -262,7 +262,7 @@ export function addDoc<T>(
262262
data: T
263263
): Promise<firestore.DocumentReference<T>> {
264264
const collRef = cast<CollectionReference<T>>(reference, CollectionReference);
265-
const firestore = cast(collRef, Firestore);
265+
const firestore = cast(collRef.firestore, Firestore);
266266
const docRef = doc(collRef);
267267

268268
const convertedValue = applyFirestoreDataConverter(collRef._converter, data);
@@ -404,7 +404,7 @@ export function onSnapshot<T>(
404404
);
405405
} else {
406406
const query = cast<Query<T>>(ref, Query);
407-
const firestore = cast(query, Firestore);
407+
const firestore = cast(query.firestore, Firestore);
408408

409409
const observer: PartialObserver<ViewSnapshot> = {
410410
next: snapshot => {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class DocumentSnapshot<T = firestore.DocumentData>
7676
this.metadata,
7777
/* converter= */ null
7878
);
79-
return this._converter.fromFirestore(snapshot);
79+
return this._converter.fromFirestore(snapshot, options);
8080
} else {
8181
const userDataWriter = new UserDataWriter(
8282
this._firestoreImpl._databaseId,

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ import { cast } from './util';
3939
import { Settings } from '../../';
4040

4141
// settings() defaults:
42-
const DEFAULT_HOST = 'firestore.googleapis.com';
43-
const DEFAULT_SSL = true;
44-
const DEFAULT_FORCE_LONG_POLLING = false; // Used by full SDK
42+
export const DEFAULT_HOST = 'firestore.googleapis.com';
43+
export const DEFAULT_SSL = true;
44+
export const DEFAULT_FORCE_LONG_POLLING = false; // Used by full SDK
4545

4646
/**
4747
* The root reference to the Firestore Lite database.
@@ -101,17 +101,13 @@ export class Firestore
101101
return this._datastorePromise;
102102
}
103103

104-
protected _makeDatabaseInfo(
105-
host?: string,
106-
ssl?: boolean,
107-
forceLongPolling?: boolean
108-
): DatabaseInfo {
104+
protected _makeDatabaseInfo(host?: string, ssl?: boolean): DatabaseInfo {
109105
return new DatabaseInfo(
110106
this._databaseId,
111107
/* persistenceKey= */ 'unsupported',
112108
host ?? DEFAULT_HOST,
113109
ssl ?? DEFAULT_SSL,
114-
forceLongPolling ?? DEFAULT_FORCE_LONG_POLLING
110+
DEFAULT_FORCE_LONG_POLLING
115111
);
116112
}
117113

packages/firestore/lite/src/api/field_value.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class FieldValueDelegate extends FieldValue implements firestore.FieldValue {
6363
}
6464

6565
export function deleteField(): firestore.FieldValue {
66-
return new FieldValueDelegate(new DeleteFieldValueImpl('delete'));
66+
return new FieldValueDelegate(new DeleteFieldValueImpl('deleteField'));
6767
}
6868

6969
export function serverTimestamp(): firestore.FieldValue {

packages/firestore/lite/src/api/reference.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ export function collection(
291291
parent: firestore.FirebaseFirestore | firestore.DocumentReference<unknown>,
292292
relativePath: string
293293
): CollectionReference<firestore.DocumentData> {
294-
validateArgType('doc', 'non-empty string', 2, relativePath);
294+
validateArgType('collection', 'non-empty string', 2, relativePath);
295295
const path = ResourcePath.fromString(relativePath);
296296
if (parent instanceof Firestore) {
297297
validateCollectionPath(path);

packages/firestore/lite/src/api/write_batch.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
import { Code, FirestoreError } from '../../../src/util/error';
2525
import { applyFirestoreDataConverter } from '../../../src/api/database';
2626
import {
27-
DocumentKeyReference,
2827
parseSetData,
2928
parseUpdateData,
3029
parseUpdateVarargs,
@@ -165,7 +164,7 @@ export class WriteBatch implements firestore.WriteBatch {
165164
export function validateReference<T>(
166165
documentRef: firestore.DocumentReference<T>,
167166
firestore: Firestore
168-
): DocumentKeyReference<T> {
167+
): DocumentReference<T> {
169168
if (documentRef.firestore !== firestore) {
170169
throw new FirestoreError(
171170
Code.INVALID_ARGUMENT,

packages/firestore/src/api/database.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
430430
) {
431431
throw new FirestoreError(
432432
Code.FAILED_PRECONDITION,
433-
'Persistence cannot be cleared after this Firestore instance is initialized.'
433+
'Persistence can only be cleared before a Firestore instance is ' +
434+
'initialized or after it is terminated.'
434435
);
435436
}
436437

@@ -515,13 +516,13 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
515516

516517
const databaseInfo = this.makeDatabaseInfo();
517518

518-
this._firestoreClient = new FirestoreClient(
519+
this._firestoreClient = new FirestoreClient(this._credentials, this._queue);
520+
521+
return this._firestoreClient.start(
519522
databaseInfo,
520-
this._credentials,
521-
this._queue
523+
componentProvider,
524+
persistenceSettings
522525
);
523-
524-
return this._firestoreClient.start(componentProvider, persistenceSettings);
525526
}
526527

527528
private static databaseIdFromApp(app: FirebaseApp): DatabaseId {

packages/firestore/src/core/firestore_client.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class FirestoreClient {
8181
// initialization completes before any other work is queued, we're cheating
8282
// with the types rather than littering the code with '!' or unnecessary
8383
// undefined checks.
84+
private databaseInfo!: DatabaseInfo;
8485
private eventMgr!: EventManager;
8586
private persistence!: Persistence;
8687
private localStore!: LocalStore;
@@ -94,7 +95,6 @@ export class FirestoreClient {
9495
private readonly clientId = AutoId.newId();
9596

9697
constructor(
97-
private databaseInfo: DatabaseInfo,
9898
private credentials: CredentialsProvider,
9999
/**
100100
* Asynchronous queue responsible for all of our internal processing. When
@@ -135,6 +135,7 @@ export class FirestoreClient {
135135
* fallback succeeds we signal success to the async queue even though the
136136
* start() itself signals failure.
137137
*
138+
* @param databaseInfo The connection information for the current instance.
138139
* @param componentProvider Provider that returns all core components.
139140
* @param persistenceSettings Settings object to configure offline
140141
* persistence.
@@ -144,10 +145,14 @@ export class FirestoreClient {
144145
* unconditionally resolved.
145146
*/
146147
start(
148+
databaseInfo: DatabaseInfo,
147149
componentProvider: ComponentProvider,
148150
persistenceSettings: PersistenceSettings
149151
): Promise<void> {
150152
this.verifyNotTerminated();
153+
154+
this.databaseInfo = databaseInfo;
155+
151156
// We defer our initialization until we get the current user from
152157
// setChangeListener(). We block the async queue until we got the initial
153158
// user and the initialization is completed. This will prevent any scheduled

packages/firestore/test/integration/api/database.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,8 @@ apiDescribe('Database', (persistence: boolean) => {
11491149
await expect(
11501150
firestore.clearPersistence()
11511151
).to.eventually.be.rejectedWith(
1152-
'Persistence cannot be cleared after this Firestore instance is initialized.'
1152+
'Persistence can only be cleared before a Firestore instance is ' +
1153+
'initialized or after it is terminated.'
11531154
);
11541155
});
11551156
}

0 commit comments

Comments
 (0)